<?php

namespace com\nlf\calendar;

use com\nlf\calendar\util\LunarUtil;
use com\nlf\calendar\util\SolarUtil;
use DateTime;
use Exception;

date_default_timezone_set('PRC');
bcscale(12);

/**
 * 农历日期
 * @package com\nlf\calendar
 */
class Lunar
{
  /**
   * 节气表头部追加农历上年末的节气名(节令：大雪)，以示区分
   * @var string
   */
  public static $JIE_QI_PREPEND = 'DA_XUE';

  /**
   * 节气表尾部追加农历下年初的节气名(气令：冬至)，以示区分
   * @var string
   */
  public static $JIE_QI_APPEND = 'DONG_ZHI';

  /**
   * 农历年初节气名(气令：冬至)
   * @var string
   */
  public static $JIE_QI_FIRST = '冬至';

  /**
   * 农历年末节气名(节令：大雪)
   * @var string
   */
  public static $JIE_QI_LAST = '大雪';

  /**
   * 节气表尾部追加阳历下年初的第一个节气名(节令：小寒)，以示区分
   * @var string
   */
  public static $JIE_APPEND_SOLAR_FIRST = 'XIAO_HAN';

  /**
   * 节气表尾部追加阳历下年初的第二个节气名(气令：大寒)，以示区分
   * @var string
   */
  public static $QI_APPEND_SOLAR_SECOND = 'DA_HAN';

  /**
   * 阳历下年初的第一个节气名(节令：小寒)
   * @var string
   */
  public static $JIE_SOLAR_FIRST = '小寒';

  /**
   * 阳历下年初的第二个节气名(气令：大寒)
   * @var string
   */
  public static $QI_SOLAR_SECOND = '大寒';

  /**
   * 节气表，国标以冬至为首个节气
   * @var array
   */
  private static $JIE_QI = array('冬至', '小寒', '大寒', '立春', '雨水', '惊蛰', '春分', '清明', '谷雨', '立夏', '小满', '芒种', '夏至', '小暑', '大暑', '立秋', '处暑', '白露', '秋分', '寒露', '霜降', '立冬', '小雪', '大雪');

  private static $NUT_B = array(2.1824, -33.75705, 36e-6, -1720, 920, 3.5069, 1256.66393, 11e-6, -132, 57, 1.3375, 16799.4182, -51e-6, -23, 10, 4.3649, -67.5141, 72e-6, 21, -9, 0.04, -628.302, 0, -14, 0, 2.36, 8328.691, 0, 7, 0, 3.46, 1884.966, 0, -5, 2, 5.44, 16833.175, 0, -4, 2, 3.69, 25128.110, 0, -3, 0, 3.55, 628.362, 0, 2, 0);
  private static $DT_AT = array(-4000, 108371.7, -13036.80, 392.000, 0.0000, -500, 17201.0, -627.82, 16.170, -0.3413, -150, 12200.6, -346.41, 5.403, -0.1593, 150, 9113.8, -328.13, -1.647, 0.0377, 500, 5707.5, -391.41, 0.915, 0.3145, 900, 2203.4, -283.45, 13.034, -0.1778, 1300, 490.1, -57.35, 2.085, -0.0072, 1600, 120.0, -9.81, -1.532, 0.1403, 1700, 10.2, -0.91, 0.510, -0.0370, 1800, 13.4, -0.72, 0.202, -0.0193, 1830, 7.8, -1.81, 0.416, -0.0247, 1860, 8.3, -0.13, -0.406, 0.0292, 1880, -5.4, 0.32, -0.183, 0.0173, 1900, -2.3, 2.06, 0.169, -0.0135, 1920, 21.2, 1.69, -0.304, 0.0167, 1940, 24.2, 1.22, -0.064, 0.0031, 1960, 33.2, 0.51, 0.231, -0.0109, 1980, 51.0, 1.29, -0.026, 0.0032, 2000, 63.87, 0.1, 0, 0, 2005, 64.7, 0.4, 0, 0, 2015, 69);
  private static $XL0 = array(10000000000, 20, 578, 920, 1100, 1124, 1136, 1148, 1217, 1226, 1229, 1229, 1229, 1229, 1937, 2363, 2618, 2633, 2660, 2666, 17534704567, 0.00000000000, 0.00000000000, 334165646, 4.669256804, 6283.075849991, 3489428, 4.6261024, 12566.1517000, 349706, 2.744118, 5753.384885, 341757, 2.828866, 3.523118, 313590, 3.627670, 77713.771468, 267622, 4.418084, 7860.419392, 234269, 6.135162, 3930.209696, 132429, 0.742464, 11506.769770, 127317, 2.037097, 529.690965, 119917, 1.109629, 1577.343542, 99025, 5.23268, 5884.92685, 90186, 2.04505, 26.29832, 85722, 3.50849, 398.14900, 77979, 1.17883, 5223.69392, 75314, 2.53339, 5507.55324, 50526, 4.58293, 18849.22755, 49238, 4.20507, 775.52261, 35666, 2.91954, 0.06731, 31709, 5.84902, 11790.62909, 28413, 1.89869, 796.29801, 27104, 0.31489, 10977.07880, 24281, 0.34481, 5486.77784, 20616, 4.80647, 2544.31442, 20539, 1.86948, 5573.14280, 20226, 2.45768, 6069.77675, 15552, 0.83306, 213.29910, 13221, 3.41118, 2942.46342, 12618, 1.08303, 20.77540, 11513, 0.64545, 0.98032, 10285, 0.63600, 4694.00295, 10190, 0.97569, 15720.83878, 10172, 4.26680, 7.11355, 9921, 6.2099, 2146.1654, 9761, 0.6810, 155.4204, 8580, 5.9832, 161000.6857, 8513, 1.2987, 6275.9623, 8471, 3.6708, 71430.6956, 7964, 1.8079, 17260.1547, 7876, 3.0370, 12036.4607, 7465, 1.7551, 5088.6288, 7387, 3.5032, 3154.6871, 7355, 4.6793, 801.8209, 6963, 0.8330, 9437.7629, 6245, 3.9776, 8827.3903, 6115, 1.8184, 7084.8968, 5696, 2.7843, 6286.5990, 5612, 4.3869, 14143.4952, 5558, 3.4701, 6279.5527, 5199, 0.1891, 12139.5535, 5161, 1.3328, 1748.0164, 5115, 0.2831, 5856.4777, 4900, 0.4874, 1194.4470, 4104, 5.3682, 8429.2413, 4094, 2.3985, 19651.0485, 3920, 6.1683, 10447.3878, 3677, 6.0413, 10213.2855, 3660, 2.5696, 1059.3819, 3595, 1.7088, 2352.8662, 3557, 1.7760, 6812.7668, 3329, 0.5931, 17789.8456, 3041, 0.4429, 83996.8473, 3005, 2.7398, 1349.8674, 2535, 3.1647, 4690.4798, 2474, 0.2148, 3.5904, 2366, 0.4847, 8031.0923, 2357, 2.0653, 3340.6124, 2282, 5.2220, 4705.7323, 2189, 5.5559, 553.5694, 2142, 1.4256, 16730.4637, 2109, 4.1483, 951.7184, 2030, 0.3713, 283.8593, 1992, 5.2221, 12168.0027, 1986, 5.7747, 6309.3742, 1912, 3.8222, 23581.2582, 1889, 5.3863, 149854.4001, 1790, 2.2149, 13367.9726, 1748, 4.5605, 135.0651, 1622, 5.9884, 11769.8537, 1508, 4.1957, 6256.7775, 1442, 4.1932, 242.7286, 1435, 3.7236, 38.0277, 1397, 4.4014, 6681.2249, 1362, 1.8893, 7632.9433, 1250, 1.1305, 5.5229, 1205, 2.6223, 955.5997, 1200, 1.0035, 632.7837, 1129, 0.1774, 4164.3120, 1083, 0.3273, 103.0928, 1052, 0.9387, 11926.2544, 1050, 5.3591, 1592.5960, 1033, 6.1998, 6438.4962, 1001, 6.0291, 5746.2713, 980, 0.999, 11371.705, 980, 5.244, 27511.468, 938, 2.624, 5760.498, 923, 0.483, 522.577, 922, 4.571, 4292.331, 905, 5.337, 6386.169, 862, 4.165, 7058.598, 841, 3.299, 7234.794, 836, 4.539, 25132.303, 813, 6.112, 4732.031, 812, 6.271, 426.598, 801, 5.821, 28.449, 787, 0.996, 5643.179, 776, 2.957, 23013.540, 769, 3.121, 7238.676, 758, 3.974, 11499.656, 735, 4.386, 316.392, 731, 0.607, 11513.883, 719, 3.998, 74.782, 706, 0.323, 263.084, 676, 5.911, 90955.552, 663, 3.665, 17298.182, 653, 5.791, 18073.705, 630, 4.717, 6836.645, 615, 1.458, 233141.314, 612, 1.075, 19804.827, 596, 3.321, 6283.009, 596, 2.876, 6283.143, 555, 2.452, 12352.853, 541, 5.392, 419.485, 531, 0.382, 31441.678, 519, 4.065, 6208.294, 513, 2.361, 10973.556, 494, 5.737, 9917.697, 450, 3.272, 11015.106, 449, 3.653, 206.186, 447, 2.064, 7079.374, 435, 4.423, 5216.580, 421, 1.906, 245.832, 413, 0.921, 3738.761, 402, 0.840, 20.355, 387, 1.826, 11856.219, 379, 2.344, 3.881, 374, 2.954, 3128.389, 370, 5.031, 536.805, 365, 1.018, 16200.773, 365, 1.083, 88860.057, 352, 5.978, 3894.182, 352, 2.056, 244287.600, 351, 3.713, 6290.189, 340, 1.106, 14712.317, 339, 0.978, 8635.942, 339, 3.202, 5120.601, 333, 0.837, 6496.375, 325, 3.479, 6133.513, 316, 5.089, 21228.392, 316, 1.328, 10873.986, 309, 3.646, 10.637, 303, 1.802, 35371.887, 296, 3.397, 9225.539, 288, 6.026, 154717.610, 281, 2.585, 14314.168, 262, 3.856, 266.607, 262, 2.579, 22483.849, 257, 1.561, 23543.231, 255, 3.949, 1990.745, 251, 3.744, 10575.407, 240, 1.161, 10984.192, 238, 0.106, 7.046, 236, 4.272, 6040.347, 234, 3.577, 10969.965, 211, 3.714, 65147.620, 210, 0.754, 13521.751, 207, 4.228, 5650.292, 202, 0.814, 170.673, 201, 4.629, 6037.244, 200, 0.381, 6172.870, 199, 3.933, 6206.810, 199, 5.197, 6262.300, 197, 1.046, 18209.330, 195, 1.070, 5230.807, 195, 4.869, 36.028, 194, 4.313, 6244.943, 192, 1.229, 709.933, 192, 5.595, 6282.096, 192, 0.602, 6284.056, 189, 3.744, 23.878, 188, 1.904, 15.252, 188, 0.867, 22003.915, 182, 3.681, 15110.466, 181, 0.491, 1.484, 179, 3.222, 39302.097, 179, 1.259, 12559.038, 62833196674749, 0.000000000000, 0.000000000000, 20605886, 2.67823456, 6283.07584999, 430343, 2.635127, 12566.151700, 42526, 1.59047, 3.52312, 11926, 5.79557, 26.29832, 10898, 2.96618, 1577.34354, 9348, 2.5921, 18849.2275, 7212, 1.1385, 529.6910, 6777, 1.8747, 398.1490, 6733, 4.4092, 5507.5532, 5903, 2.8880, 5223.6939, 5598, 2.1747, 155.4204, 4541, 0.3980, 796.2980, 3637, 0.4662, 775.5226, 2896, 2.6471, 7.1135, 2084, 5.3414, 0.9803, 1910, 1.8463, 5486.7778, 1851, 4.9686, 213.2991, 1729, 2.9912, 6275.9623, 1623, 0.0322, 2544.3144, 1583, 1.4305, 2146.1654, 1462, 1.2053, 10977.0788, 1246, 2.8343, 1748.0164, 1188, 3.2580, 5088.6288, 1181, 5.2738, 1194.4470, 1151, 2.0750, 4694.0030, 1064, 0.7661, 553.5694, 997, 1.303, 6286.599, 972, 4.239, 1349.867, 945, 2.700, 242.729, 858, 5.645, 951.718, 758, 5.301, 2352.866, 639, 2.650, 9437.763, 610, 4.666, 4690.480, 583, 1.766, 1059.382, 531, 0.909, 3154.687, 522, 5.661, 71430.696, 520, 1.854, 801.821, 504, 1.425, 6438.496, 433, 0.241, 6812.767, 426, 0.774, 10447.388, 413, 5.240, 7084.897, 374, 2.001, 8031.092, 356, 2.429, 14143.495, 350, 4.800, 6279.553, 337, 0.888, 12036.461, 337, 3.862, 1592.596, 325, 3.400, 7632.943, 322, 0.616, 8429.241, 318, 3.188, 4705.732, 297, 6.070, 4292.331, 295, 1.431, 5746.271, 290, 2.325, 20.355, 275, 0.935, 5760.498, 270, 4.804, 7234.794, 253, 6.223, 6836.645, 228, 5.003, 17789.846, 225, 5.672, 11499.656, 215, 5.202, 11513.883, 208, 3.955, 10213.286, 208, 2.268, 522.577, 206, 2.224, 5856.478, 206, 2.550, 25132.303, 203, 0.910, 6256.778, 189, 0.532, 3340.612, 188, 4.735, 83996.847, 179, 1.474, 4164.312, 178, 3.025, 5.523, 177, 3.026, 5753.385, 159, 4.637, 3.286, 157, 6.124, 5216.580, 155, 3.077, 6681.225, 154, 4.200, 13367.973, 143, 1.191, 3894.182, 138, 3.093, 135.065, 136, 4.245, 426.598, 134, 5.765, 6040.347, 128, 3.085, 5643.179, 127, 2.092, 6290.189, 125, 3.077, 11926.254, 125, 3.445, 536.805, 114, 3.244, 12168.003, 112, 2.318, 16730.464, 111, 3.901, 11506.770, 111, 5.320, 23.878, 105, 3.750, 7860.419, 103, 2.447, 1990.745, 96, 0.82, 3.88, 96, 4.08, 6127.66, 91, 5.42, 206.19, 91, 0.42, 7079.37, 88, 5.17, 11790.63, 81, 0.34, 9917.70, 80, 3.89, 10973.56, 78, 2.40, 1589.07, 78, 2.58, 11371.70, 77, 3.98, 955.60, 77, 3.36, 36.03, 76, 1.30, 103.09, 75, 5.18, 10969.97, 75, 4.96, 6496.37, 73, 5.21, 38.03, 72, 2.65, 6309.37, 70, 5.61, 3738.76, 69, 2.60, 3496.03, 69, 0.39, 15.25, 69, 2.78, 20.78, 65, 1.13, 7058.60, 64, 4.28, 28.45, 61, 5.63, 10984.19, 60, 0.73, 419.48, 60, 5.28, 10575.41, 58, 5.55, 17298.18, 58, 3.19, 4732.03, 5291887, 0.0000000, 0.0000000, 871984, 1.072097, 6283.075850, 30913, 0.86729, 12566.15170, 2734, 0.0530, 3.5231, 1633, 5.1883, 26.2983, 1575, 3.6846, 155.4204, 954, 0.757, 18849.228, 894, 2.057, 77713.771, 695, 0.827, 775.523, 506, 4.663, 1577.344, 406, 1.031, 7.114, 381, 3.441, 5573.143, 346, 5.141, 796.298, 317, 6.053, 5507.553, 302, 1.192, 242.729, 289, 6.117, 529.691, 271, 0.306, 398.149, 254, 2.280, 553.569, 237, 4.381, 5223.694, 208, 3.754, 0.980, 168, 0.902, 951.718, 153, 5.759, 1349.867, 145, 4.364, 1748.016, 134, 3.721, 1194.447, 125, 2.948, 6438.496, 122, 2.973, 2146.165, 110, 1.271, 161000.686, 104, 0.604, 3154.687, 100, 5.986, 6286.599, 92, 4.80, 5088.63, 89, 5.23, 7084.90, 83, 3.31, 213.30, 76, 3.42, 5486.78, 71, 6.19, 4690.48, 68, 3.43, 4694.00, 65, 1.60, 2544.31, 64, 1.98, 801.82, 61, 2.48, 10977.08, 50, 1.44, 6836.65, 49, 2.34, 1592.60, 46, 1.31, 4292.33, 46, 3.81, 149854.40, 43, 0.04, 7234.79, 40, 4.94, 7632.94, 39, 1.57, 71430.70, 38, 3.17, 6309.37, 35, 0.99, 6040.35, 35, 0.67, 1059.38, 31, 3.18, 2352.87, 31, 3.55, 8031.09, 30, 1.92, 10447.39, 30, 2.52, 6127.66, 28, 4.42, 9437.76, 28, 2.71, 3894.18, 27, 0.67, 25132.30, 26, 5.27, 6812.77, 25, 0.55, 6279.55, 23, 1.38, 4705.73, 22, 0.64, 6256.78, 20, 6.07, 640.88, 28923, 5.84384, 6283.07585, 3496, 0.0000, 0.0000, 1682, 5.4877, 12566.1517, 296, 5.196, 155.420, 129, 4.722, 3.523, 71, 5.30, 18849.23, 64, 5.97, 242.73, 40, 3.79, 553.57, 11408, 3.14159, 0.00000, 772, 4.134, 6283.076, 77, 3.84, 12566.15, 42, 0.42, 155.42, 88, 3.14, 0.00, 17, 2.77, 6283.08, 5, 2.01, 155.42, 3, 2.21, 12566.15, 27962, 3.19870, 84334.66158, 10164, 5.42249, 5507.55324, 8045, 3.8801, 5223.6939, 4381, 3.7044, 2352.8662, 3193, 4.0003, 1577.3435, 2272, 3.9847, 1047.7473, 1814, 4.9837, 6283.0758, 1639, 3.5646, 5856.4777, 1444, 3.7028, 9437.7629, 1430, 3.4112, 10213.2855, 1125, 4.8282, 14143.4952, 1090, 2.0857, 6812.7668, 1037, 4.0566, 71092.8814, 971, 3.473, 4694.003, 915, 1.142, 6620.890, 878, 4.440, 5753.385, 837, 4.993, 7084.897, 770, 5.554, 167621.576, 719, 3.602, 529.691, 692, 4.326, 6275.962, 558, 4.410, 7860.419, 529, 2.484, 4705.732, 521, 6.250, 18073.705, 903, 3.897, 5507.553, 618, 1.730, 5223.694, 380, 5.244, 2352.866, 166, 1.627, 84334.662, 10001398880, 0.00000000000, 0.00000000000, 167069963, 3.098463508, 6283.075849991, 1395602, 3.0552461, 12566.1517000, 308372, 5.198467, 77713.771468, 162846, 1.173877, 5753.384885, 157557, 2.846852, 7860.419392, 92480, 5.45292, 11506.76977, 54244, 4.56409, 3930.20970, 47211, 3.66100, 5884.92685, 34598, 0.96369, 5507.55324, 32878, 5.89984, 5223.69392, 30678, 0.29867, 5573.14280, 24319, 4.27350, 11790.62909, 21183, 5.84715, 1577.34354, 18575, 5.02194, 10977.07880, 17484, 3.01194, 18849.22755, 10984, 5.05511, 5486.77784, 9832, 0.8868, 6069.7768, 8650, 5.6896, 15720.8388, 8583, 1.2708, 161000.6857, 6490, 0.2725, 17260.1547, 6292, 0.9218, 529.6910, 5706, 2.0137, 83996.8473, 5574, 5.2416, 71430.6956, 4938, 3.2450, 2544.3144, 4696, 2.5781, 775.5226, 4466, 5.5372, 9437.7629, 4252, 6.0111, 6275.9623, 3897, 5.3607, 4694.0030, 3825, 2.3926, 8827.3903, 3749, 0.8295, 19651.0485, 3696, 4.9011, 12139.5535, 3566, 1.6747, 12036.4607, 3454, 1.8427, 2942.4634, 3319, 0.2437, 7084.8968, 3192, 0.1837, 5088.6288, 3185, 1.7778, 398.1490, 2846, 1.2134, 6286.5990, 2779, 1.8993, 6279.5527, 2628, 4.5890, 10447.3878, 2460, 3.7866, 8429.2413, 2393, 4.9960, 5856.4777, 2359, 0.2687, 796.2980, 2329, 2.8078, 14143.4952, 2210, 1.9500, 3154.6871, 2035, 4.6527, 2146.1654, 1951, 5.3823, 2352.8662, 1883, 0.6731, 149854.4001, 1833, 2.2535, 23581.2582, 1796, 0.1987, 6812.7668, 1731, 6.1520, 16730.4637, 1717, 4.4332, 10213.2855, 1619, 5.2316, 17789.8456, 1381, 5.1896, 8031.0923, 1364, 3.6852, 4705.7323, 1314, 0.6529, 13367.9726, 1041, 4.3329, 11769.8537, 1017, 1.5939, 4690.4798, 998, 4.201, 6309.374, 966, 3.676, 27511.468, 874, 6.064, 1748.016, 779, 3.674, 12168.003, 771, 0.312, 7632.943, 756, 2.626, 6256.778, 746, 5.648, 11926.254, 693, 2.924, 6681.225, 680, 1.423, 23013.540, 674, 0.563, 3340.612, 663, 5.661, 11371.705, 659, 3.136, 801.821, 648, 2.650, 19804.827, 615, 3.029, 233141.314, 612, 5.134, 1194.447, 563, 4.341, 90955.552, 552, 2.091, 17298.182, 534, 5.100, 31441.678, 531, 2.407, 11499.656, 523, 4.624, 6438.496, 513, 5.324, 11513.883, 477, 0.256, 11856.219, 461, 1.722, 7234.794, 458, 3.766, 6386.169, 458, 4.466, 5746.271, 423, 1.055, 5760.498, 422, 1.557, 7238.676, 415, 2.599, 7058.598, 401, 3.030, 1059.382, 397, 1.201, 1349.867, 379, 4.907, 4164.312, 360, 5.707, 5643.179, 352, 3.626, 244287.600, 348, 0.761, 10973.556, 342, 3.001, 4292.331, 336, 4.546, 4732.031, 334, 3.138, 6836.645, 324, 4.164, 9917.697, 316, 1.691, 11015.106, 307, 0.238, 35371.887, 298, 1.306, 6283.143, 298, 1.750, 6283.009, 293, 5.738, 16200.773, 286, 5.928, 14712.317, 281, 3.515, 21228.392, 280, 5.663, 8635.942, 277, 0.513, 26.298, 268, 4.207, 18073.705, 266, 0.900, 12352.853, 260, 2.962, 25132.303, 255, 2.477, 6208.294, 242, 2.800, 709.933, 231, 1.054, 22483.849, 229, 1.070, 14314.168, 216, 1.314, 154717.610, 215, 6.038, 10873.986, 200, 0.561, 7079.374, 198, 2.614, 951.718, 197, 4.369, 167283.762, 186, 2.861, 5216.580, 183, 1.660, 39302.097, 183, 5.912, 3738.761, 175, 2.145, 6290.189, 173, 2.168, 10575.407, 171, 3.702, 1592.596, 171, 1.343, 3128.389, 164, 5.550, 6496.375, 164, 5.856, 10984.192, 161, 1.998, 10969.965, 161, 1.909, 6133.513, 157, 4.955, 25158.602, 154, 6.216, 23543.231, 153, 5.357, 13521.751, 150, 5.770, 18209.330, 150, 5.439, 155.420, 139, 1.778, 9225.539, 139, 1.626, 5120.601, 128, 2.460, 13916.019, 123, 0.717, 143571.324, 122, 2.654, 88860.057, 121, 4.414, 3894.182, 121, 1.192, 3.523, 120, 4.030, 553.569, 119, 1.513, 17654.781, 117, 3.117, 14945.316, 113, 2.698, 6040.347, 110, 3.085, 43232.307, 109, 0.998, 955.600, 108, 2.939, 17256.632, 107, 5.285, 65147.620, 103, 0.139, 11712.955, 103, 5.850, 213.299, 102, 3.046, 6037.244, 101, 2.842, 8662.240, 100, 3.626, 6262.300, 98, 2.36, 6206.81, 98, 5.11, 6172.87, 98, 2.00, 15110.47, 97, 2.67, 5650.29, 97, 2.75, 6244.94, 96, 4.02, 6282.10, 96, 5.31, 6284.06, 92, 0.10, 29088.81, 85, 3.26, 20426.57, 84, 2.60, 28766.92, 81, 3.58, 10177.26, 80, 5.81, 5230.81, 78, 2.53, 16496.36, 77, 4.06, 6127.66, 73, 0.04, 5481.25, 72, 5.96, 12559.04, 72, 5.92, 4136.91, 71, 5.49, 22003.91, 70, 3.41, 7.11, 69, 0.62, 11403.68, 69, 3.90, 1589.07, 69, 1.96, 12416.59, 69, 4.51, 426.60, 67, 1.61, 11087.29, 66, 4.50, 47162.52, 66, 5.08, 283.86, 66, 4.32, 16858.48, 65, 1.04, 6062.66, 64, 1.59, 18319.54, 63, 5.70, 45892.73, 63, 4.60, 66567.49, 63, 3.82, 13517.87, 62, 2.62, 11190.38, 61, 1.54, 33019.02, 60, 5.58, 10344.30, 60, 5.38, 316428.23, 60, 5.78, 632.78, 59, 6.12, 9623.69, 57, 0.16, 17267.27, 57, 3.86, 6076.89, 57, 1.98, 7668.64, 56, 4.78, 20199.09, 55, 4.56, 18875.53, 55, 3.51, 17253.04, 54, 3.07, 226858.24, 54, 4.83, 18422.63, 53, 5.02, 12132.44, 52, 3.63, 5333.90, 52, 0.97, 155427.54, 51, 3.36, 20597.24, 50, 0.99, 11609.86, 50, 2.21, 1990.75, 48, 1.62, 12146.67, 48, 1.17, 12569.67, 47, 4.62, 5436.99, 47, 1.81, 12562.63, 47, 0.59, 21954.16, 47, 0.76, 7342.46, 46, 0.27, 4590.91, 46, 3.77, 156137.48, 45, 5.66, 10454.50, 44, 5.84, 3496.03, 43, 0.24, 17996.03, 41, 5.93, 51092.73, 41, 4.21, 12592.45, 40, 5.14, 1551.05, 40, 5.28, 15671.08, 39, 3.69, 18052.93, 39, 4.94, 24356.78, 38, 2.72, 11933.37, 38, 5.23, 7477.52, 38, 4.99, 9779.11, 37, 3.70, 9388.01, 37, 4.44, 4535.06, 36, 2.16, 28237.23, 36, 2.54, 242.73, 36, 0.22, 5429.88, 35, 6.15, 19800.95, 35, 2.92, 36949.23, 34, 5.63, 2379.16, 34, 5.73, 16460.33, 34, 5.11, 5849.36, 33, 6.19, 6268.85, 10301861, 1.10748970, 6283.07584999, 172124, 1.064423, 12566.151700, 70222, 3.14159, 0.00000, 3235, 1.0217, 18849.2275, 3080, 2.8435, 5507.5532, 2497, 1.3191, 5223.6939, 1849, 1.4243, 1577.3435, 1008, 5.9138, 10977.0788, 865, 1.420, 6275.962, 863, 0.271, 5486.778, 507, 1.686, 5088.629, 499, 6.014, 6286.599, 467, 5.987, 529.691, 440, 0.518, 4694.003, 410, 1.084, 9437.763, 387, 4.750, 2544.314, 375, 5.071, 796.298, 352, 0.023, 83996.847, 344, 0.949, 71430.696, 341, 5.412, 775.523, 322, 6.156, 2146.165, 286, 5.484, 10447.388, 284, 3.420, 2352.866, 255, 6.132, 6438.496, 252, 0.243, 398.149, 243, 3.092, 4690.480, 225, 3.689, 7084.897, 220, 4.952, 6812.767, 219, 0.420, 8031.092, 209, 1.282, 1748.016, 193, 5.314, 8429.241, 185, 1.820, 7632.943, 175, 3.229, 6279.553, 173, 1.537, 4705.732, 158, 4.097, 11499.656, 158, 5.539, 3154.687, 150, 3.633, 11513.883, 148, 3.222, 7234.794, 147, 3.653, 1194.447, 144, 0.817, 14143.495, 135, 6.151, 5746.271, 134, 4.644, 6836.645, 128, 2.693, 1349.867, 123, 5.650, 5760.498, 118, 2.577, 13367.973, 113, 3.357, 17789.846, 110, 4.497, 4292.331, 108, 5.828, 12036.461, 102, 5.621, 6256.778, 99, 1.14, 1059.38, 98, 0.66, 5856.48, 93, 2.32, 10213.29, 92, 0.77, 16730.46, 88, 1.50, 11926.25, 86, 1.42, 5753.38, 85, 0.66, 155.42, 81, 1.64, 6681.22, 80, 4.11, 951.72, 66, 4.55, 5216.58, 65, 0.98, 25132.30, 64, 4.19, 6040.35, 64, 0.52, 6290.19, 63, 1.51, 5643.18, 59, 6.18, 4164.31, 57, 2.30, 10973.56, 55, 2.32, 11506.77, 55, 2.20, 1592.60, 55, 5.27, 3340.61, 54, 5.54, 553.57, 53, 5.04, 9917.70, 53, 0.92, 11371.70, 52, 3.98, 17298.18, 52, 3.60, 10969.97, 49, 5.91, 3894.18, 49, 2.51, 6127.66, 48, 1.67, 12168.00, 46, 0.31, 801.82, 42, 3.70, 10575.41, 42, 4.05, 10984.19, 40, 2.17, 7860.42, 40, 4.17, 26.30, 38, 5.82, 7058.60, 37, 3.39, 6496.37, 36, 1.08, 6309.37, 36, 5.34, 7079.37, 34, 3.62, 11790.63, 32, 0.32, 16200.77, 31, 4.24, 3738.76, 29, 4.55, 11856.22, 29, 1.26, 8635.94, 27, 3.45, 5884.93, 26, 5.08, 10177.26, 26, 5.38, 21228.39, 24, 2.26, 11712.96, 24, 1.05, 242.73, 24, 5.59, 6069.78, 23, 3.63, 6284.06, 23, 1.64, 4732.03, 22, 3.46, 213.30, 21, 1.05, 3496.03, 21, 3.92, 13916.02, 21, 4.01, 5230.81, 20, 5.16, 12352.85, 20, 0.69, 1990.75, 19, 2.73, 6062.66, 19, 5.01, 11015.11, 18, 6.04, 6283.01, 18, 2.85, 7238.68, 18, 5.60, 6283.14, 18, 5.16, 17253.04, 18, 2.54, 14314.17, 17, 1.58, 7.11, 17, 0.98, 3930.21, 17, 4.75, 17267.27, 16, 2.19, 6076.89, 16, 2.19, 18073.70, 16, 6.12, 3.52, 16, 4.61, 9623.69, 16, 3.40, 16496.36, 15, 0.19, 9779.11, 15, 5.30, 13517.87, 15, 4.26, 3128.39, 15, 0.81, 709.93, 14, 0.50, 25158.60, 14, 4.38, 4136.91, 13, 0.98, 65147.62, 13, 3.31, 154717.61, 13, 2.11, 1589.07, 13, 1.92, 22483.85, 12, 6.03, 9225.54, 12, 1.53, 12559.04, 12, 5.82, 6282.10, 12, 5.61, 5642.20, 12, 2.38, 167283.76, 12, 0.39, 12132.44, 12, 3.98, 4686.89, 12, 5.81, 12569.67, 12, 0.56, 5849.36, 11, 0.45, 6172.87, 11, 5.80, 16858.48, 11, 6.22, 12146.67, 11, 2.27, 5429.88, 435939, 5.784551, 6283.075850, 12363, 5.57935, 12566.15170, 1234, 3.1416, 0.0000, 879, 3.628, 77713.771, 569, 1.870, 5573.143, 330, 5.470, 18849.228, 147, 4.480, 5507.553, 110, 2.842, 161000.686, 101, 2.815, 5223.694, 85, 3.11, 1577.34, 65, 5.47, 775.52, 61, 1.38, 6438.50, 50, 4.42, 6286.60, 47, 3.66, 7084.90, 46, 5.39, 149854.40, 42, 0.90, 10977.08, 40, 3.20, 5088.63, 35, 1.81, 5486.78, 32, 5.35, 3154.69, 30, 3.52, 796.30, 29, 4.62, 4690.48, 28, 1.84, 4694.00, 27, 3.14, 71430.70, 27, 6.17, 6836.65, 26, 1.42, 2146.17, 25, 2.81, 1748.02, 24, 2.18, 155.42, 23, 4.76, 7234.79, 21, 3.38, 7632.94, 21, 0.22, 4705.73, 20, 4.22, 1349.87, 20, 2.01, 1194.45, 20, 4.58, 529.69, 19, 1.59, 6309.37, 18, 5.70, 6040.35, 18, 6.03, 4292.33, 17, 2.90, 9437.76, 17, 2.00, 8031.09, 17, 5.78, 83996.85, 16, 0.05, 2544.31, 15, 0.95, 6127.66, 14, 0.36, 10447.39, 14, 1.48, 2352.87, 13, 0.77, 553.57, 13, 5.48, 951.72, 13, 5.27, 6279.55, 13, 3.76, 6812.77, 11, 5.41, 6256.78, 10, 0.68, 1592.60, 10, 4.95, 398.15, 10, 1.15, 3894.18, 10, 5.20, 244287.60, 10, 1.94, 11856.22, 9, 5.39, 25132.30, 8, 6.18, 1059.38, 8, 0.69, 8429.24, 8, 5.85, 242.73, 7, 5.26, 14143.50, 7, 0.52, 801.82, 6, 2.24, 8635.94, 6, 4.00, 13367.97, 6, 2.77, 90955.55, 6, 5.17, 7058.60, 5, 1.46, 233141.31, 5, 4.13, 7860.42, 5, 3.91, 26.30, 5, 3.89, 12036.46, 5, 5.58, 6290.19, 5, 5.54, 1990.75, 5, 0.83, 11506.77, 5, 6.22, 6681.22, 4, 5.26, 10575.41, 4, 1.91, 7477.52, 4, 0.43, 10213.29, 4, 1.09, 709.93, 4, 5.09, 11015.11, 4, 4.22, 88860.06, 4, 3.57, 7079.37, 4, 1.98, 6284.06, 4, 3.93, 10973.56, 4, 6.18, 9917.70, 4, 0.36, 10177.26, 4, 2.75, 3738.76, 4, 3.33, 5643.18, 4, 5.36, 25158.60, 14459, 4.27319, 6283.07585, 673, 3.917, 12566.152, 77, 0.00, 0.00, 25, 3.73, 18849.23, 4, 2.80, 6286.60, 386, 2.564, 6283.076, 31, 2.27, 12566.15, 5, 3.44, 5573.14, 2, 2.05, 18849.23, 1, 2.06, 77713.77, 1, 4.41, 161000.69, 1, 3.82, 149854.40, 1, 4.08, 6127.66, 1, 5.26, 6438.50, 9, 1.22, 6283.08, 1, 0.66, 12566.15);
  private static $QI_KB = array(1640650.479938, 15.21842500, 1642476.703182, 15.21874996, 1683430.515601, 15.218750011, 1752157.640664, 15.218749978, 1807675.003759, 15.218620279, 1883627.765182, 15.218612292, 1907369.128100, 15.218449176, 1936603.140413, 15.218425000, 1939145.524180, 15.218466998, 1947180.798300, 15.218524844, 1964362.041824, 15.218533526, 1987372.340971, 15.218513908, 1999653.819126, 15.218530782, 2007445.469786, 15.218535181, 2021324.917146, 15.218526248, 2047257.232342, 15.218519654, 2070282.898213, 15.218425000, 2073204.872850, 15.218515221, 2080144.500926, 15.218530782, 2086703.688963, 15.218523776, 2110033.182763, 15.218425000, 2111190.300888, 15.218425000, 2113731.271005, 15.218515671, 2120670.840263, 15.218425000, 2123973.309063, 15.218425000, 2125068.997336, 15.218477932, 2136026.312633, 15.218472436, 2156099.495538, 15.218425000, 2159021.324663, 15.218425000, 2162308.575254, 15.218461742, 2178485.706538, 15.218425000, 2178759.662849, 15.218445786, 2185334.020800, 15.218425000, 2187525.481425, 15.218425000, 2188621.191481, 15.218437494, 2322147.76);
  private static $QB = '0000000000000200000001000000000000222000000000000000000000000000000000000000000000000000000000000000000000000200000001010000000000202002000000000000000000000000000000020000000000000020000000000000000000002000000000010000020000002002000000000000000010000000000000100100000000000020000010000000000020000000020000010000000002000002002000000000000000000000000100100101000000000020000000001000000020000000020000010000000002000002000000000000000000020000000000100101000200000020200000001000000020000000000000000000000002000000000000000000000000220000000000000010000200000000200000001000000000000000000000000000000002000200000000000000002000222000000000000010000000000000200000001000100000000000000000000000000000000200000001000000000000222000000000000010000000000000000000000000100000000000200000000000000000000200200001000000000000222002000000000000000000000000000000000000000000000020000000000000000000000200000000010000000000202002000000000000000000000000000000100000000000000020000010000000000000000000020000010000000000002002002000000000000000000000000000100100000000000020000000000000000020000000020000010000000002000002000000000000000001000000000000100101000000000020200000001000000020000000000000000000000002000000000000000000000000020000000000000101000200000020200000001000000020000000000000000000000002000200000000000000000000020000000000000001000200000000200000001000000000000000000000000000000002000200000000000000000000222000000000000010000000000000000000000000000000000000000000000000000000000200000001000000002000222000000000000000000000000000000000000000100000000000000000000000010000000200000000010000000000222002000000000000000000000000000000100000000000000020000010000000000000000200020000010000000000202002002000000000000000000000000100100000000000000020000000000000000000000000020000010000000000002002000000000000000000000000000000100100000000000020200000000000000000000000020000000000000002000002000000000000000000000000000000000100000000000020200000001000000020000000000000000000000002000000000000000000000000020000000000000111000000000000200000001000000020000000000000000000000002000200000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000020000000000000000000000000000000200000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000010000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000020000002000000000000000000000000000000000000000000000000000000000010000000200000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001000000002000000000000000000000000000000000100000000000000000000001000010000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000100000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000001000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000000000010000000000000000001000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100100000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';

  /**
   * 年
   * @var int
   */
  private $year;

  /**
   * 月
   * @var int
   */
  private $month;

  /**
   * 日
   * @var int
   */
  private $day;

  /**
   * 时
   * @var int
   */
  private $hour;

  /**
   * 分
   * @var int
   */
  private $minute;

  /**
   * 秒
   * @var int
   */
  private $second;

  /**
   * 对应阳历
   * @var Solar
   */
  private $solar;

  /**
   * 相对于基准日的偏移天数
   * @var int
   */
  private $dayOffset;

  /**
   * 时对应的天干下标，0-9
   * @var int
   */
  private $timeGanIndex;

  /**
   * 时对应的地支下标，0-11
   * @var int
   */
  private $timeZhiIndex;

  /**
   * 日对应的天干下标，0-9
   * @var int
   */
  private $dayGanIndex;

  /**
   * 日对应的天干下标（八字流派1，晚子时日柱算明天），0-9
   * @var int
   */
  private $dayGanIndexExact;

  /**
   * 日对应的天干下标（八字流派2，晚子时日柱算当天），0-9
   * @var int
   */
  private $dayGanIndexExact2;

  /**
   * 日对应的地支下标，0-11
   * @var int
   */
  private $dayZhiIndex;

  /**
   * 日对应的地支下标（八字流派1，晚子时日柱算明天），0-9
   * @var int
   */
  private $dayZhiIndexExact;

  /**
   * 日对应的地支下标（八字流派1，晚子时日柱算当天），0-9
   * @var int
   */
  private $dayZhiIndexExact2;

  /**
   * 月对应的天干下标（以节交接当天起算），0-9
   * @var int
   */
  private $monthGanIndex;

  /**
   * 月对应的地支下标（以节交接当天起算），0-11
   * @var int
   */
  private $monthZhiIndex;

  /**
   * 月对应的天干下标（最精确的，供八字用，以节交接时刻起算），0-9
   * @var int
   */
  private $monthGanIndexExact;

  /**
   * 月对应的地支下标（最精确的，供八字用，以节交接时刻起算），0-11
   * @var int
   */
  private $monthZhiIndexExact;

  /**
   * 年对应的天干下标（国标，以正月初一为起点），0-9
   * @var int
   */
  private $yearGanIndex;

  /**
   * 年对应的地支下标（国标，以正月初一为起点），0-11
   * @var int
   */
  private $yearZhiIndex;

  /**
   * 年对应的天干下标（月干计算用，以立春为起点），0-9
   * @var int
   */
  private $yearGanIndexByLiChun;

  /**
   * 年对应的地支下标（月支计算用，以立春为起点），0-11
   * @var int
   */
  private $yearZhiIndexByLiChun;

  /**
   * 年对应的天干下标（最精确的，供八字用，以立春交接时刻为起点），0-9
   * @var int
   */
  private $yearGanIndexExact;

  /**
   * 年对应的地支下标（最精确的，供八字用，以立春交接时刻为起点），0-11
   * @var int
   */
  private $yearZhiIndexExact;

  /**
   * 周下标，0-6
   * @var int
   */
  private $weekIndex;

  /**
   * 24节气表（对应阳历的准确时刻）
   * @var array
   */
  private $jieQi = array();

  /**
   * 八字
   * @var EightChar
   */
  private $eightChar = null;

  function __construct($year, $month, $day, $hour, $minute, $second)
  {
    $this->year = $year;
    $this->month = $month;
    $this->day = $day;
    $this->hour = $hour;
    $this->minute = $minute;
    $this->second = $second;
    $this->dayOffset = LunarUtil::computeAddDays($year, $month, $day);
    $this->solar = $this->toSolar();
    $this->compute();
  }

  /**
   * 转换为阳历日期
   * @return Solar|null
   */
  private function toSolar()
  {
    try {
      $date = new DateTime(SolarUtil::$BASE_YEAR . '-' . SolarUtil::$BASE_MONTH . '-' . SolarUtil::$BASE_DAY . ' ' . $this->hour . ':' . $this->minute . ':' . $this->second);
    } catch (Exception $e) {
      return null;
    }
    $date->modify($this->dayOffset . ' day');
    return Solar::fromDate($date);
  }

  /**
   * 通过指定农历年月日获取农历
   * @param int $lunarYear 年（农历）
   * @param int $lunarMonth 月（农历），1到12，闰月为负，即闰2月=-2
   * @param int $lunarDay 日（农历），1到30
   * @return Lunar
   */
  public static function fromYmd($lunarYear, $lunarMonth, $lunarDay)
  {
    return new Lunar($lunarYear, $lunarMonth, $lunarDay, 0, 0, 0);
  }

  /**
   * 通过指定农历年月日时分秒获取农历
   * @param int $lunarYear 年（农历）
   * @param int $lunarMonth 月（农历），1到12，闰月为负，即闰2月=-2
   * @param int $lunarDay 日（农历），1到30
   * @param int $hour 小时（阳历）
   * @param int $minute 分钟（阳历）
   * @param int $second 秒钟（阳历）
   * @return Lunar
   */
  public static function fromYmdHms($lunarYear, $lunarMonth, $lunarDay, $hour, $minute, $second)
  {
    return new Lunar($lunarYear, $lunarMonth, $lunarDay, $hour, $minute, $second);
  }

  /**
   * 通过阳历日期初始化
   * @param DateTime $date 阳历日期
   * @return Lunar
   */
  public static function fromDate($date)
  {
    $solar = Solar::fromDate($date);
    $y = $solar->getYear();
    $m = $solar->getMonth();
    $d = $solar->getDay();
    if ($y < 2000) {
      $startYear = SolarUtil::$BASE_YEAR;
      $startMonth = SolarUtil::$BASE_MONTH;
      $startDay = SolarUtil::$BASE_DAY;
      $lunarYear = LunarUtil::$BASE_YEAR;
      $lunarMonth = LunarUtil::$BASE_MONTH;
      $lunarDay = LunarUtil::$BASE_DAY;
    } else {
      $startYear = SolarUtil::$BASE_YEAR + 99;
      $startMonth = 1;
      $startDay = 1;
      $lunarYear = LunarUtil::$BASE_YEAR + 99;
      $lunarMonth = 11;
      $lunarDay = 25;
    }
    $diff = 0;
    for ($i = $startYear; $i < $y; $i++) {
      $diff += 365;
      if (SolarUtil::isLeapYear($i)) {
        $diff += 1;
      }
    }
    for ($i = $startMonth; $i < $m; $i++) {
      $diff += SolarUtil::getDaysOfMonth($y, $i);
    }
    $diff += $d - $startDay;
    $lunarDay += $diff;
    $lastDate = LunarUtil::getDaysOfMonth($lunarYear, $lunarMonth);
    while ($lunarDay > $lastDate) {
      $lunarDay -= $lastDate;
      $lunarMonth = LunarUtil::nextMonth($lunarYear, $lunarMonth);
      if ($lunarMonth == 1) {
        $lunarYear++;
      }
      $lastDate = LunarUtil::getDaysOfMonth($lunarYear, $lunarMonth);
    }
    return new Lunar($lunarYear, $lunarMonth, $lunarDay, $solar->getHour(), $solar->getMinute(), $solar->getSecond());
  }

  private function nutationLon2($t)
  {
    $t2 = $t * $t;
    $dl = 0;
    for ($i = 0, $j = count(Lunar::$NUT_B); $i < $j; $i += 5) {
      if ($i == 0) {
        $a = -1.742 * $t;
      } else {
        $a = 0;
      }
      $dl += (Lunar::$NUT_B[$i + 3] + $a) * sin(Lunar::$NUT_B[$i] + Lunar::$NUT_B[$i + 1] * $t + Lunar::$NUT_B[$i + 2] * $t2);
    }
    return $dl / 100 / (180 * 3600 / pi());
  }

  private function eLon($t, $n)
  {
    $t /= 10;
    $v = 0;
    $tn = 1;
    $pn = 1;
    $m0 = Lunar::$XL0[$pn + 1] - Lunar::$XL0[$pn];
    for ($i = 0; $i < 6; $i++, $tn *= $t) {
      $n1 = intval(floor(Lunar::$XL0[$pn + $i]));
      $n2 = intval(floor(Lunar::$XL0[$pn + 1 + $i]));
      $n0 = $n2 - $n1;
      if ($n0 == 0) {
        continue;
      }
      if ($n < 0) {
        $m = $n2;
      } else {
        $m = intval(floor(3 * $n * $n0 / $m0 + 0.5)) + $n1;
        if ($i != 0) {
          $m += 3;
        }
        if ($m > $n2) {
          $m = $n2;
        }
      }
      $c = 0;
      for ($j = $n1; $j < $m; $j += 3) {
        $c += Lunar::$XL0[$j] * cos(Lunar::$XL0[$j + 1] + $t * Lunar::$XL0[$j + 2]);
      }
      $v += $c * $tn;
    }
    $v /= Lunar::$XL0[0];
    $t2 = $t * $t;
    $t3 = $t2 * $t;
    $v += (-0.0728 - 2.7702 * $t - 1.1019 * $t2 - 0.0996 * $t3) / (180 * 3600 / pi());
    return $v;
  }

  private function gxcSunLon($t)
  {
    $v = -0.043126 + 628.301955 * $t - 0.000002732 * $t * $t;
    $e = 0.016708634 - 0.000042037 * $t - 0.0000001267 * $t * $t;
    return -20.49552 * (1 + $e * cos($v)) / (180 * 3600 / pi());
  }

  private function ev($t)
  {
    $f = 628.307585 * $t;
    return 628.332 + 21 * sin(1.527 + $f) + 0.44 * sin(1.48 + $f * 2) + 0.129 * sin(5.82 + $f) * $t + 0.00055 * sin(4.21 + $f) * $t * $t;
  }

  private function saLon($t, $n)
  {
    return $this->eLon($t, $n) + $this->nutationLon2($t) + $this->gxcSunLon($t) + pi();
  }

  private function dtExt($y, $jsd)
  {
    $dy = ($y - 1820) / 100;
    return -20 + $jsd * $dy * $dy;
  }

  private function dtCalc($y)
  {
    $size = count(Lunar::$DT_AT);
    $y0 = Lunar::$DT_AT[$size - 2];
    $t0 = Lunar::$DT_AT[$size - 1];
    if ($y >= $y0) {
      $jsd = 31;
      if ($y > $y0 + 100) {
        return $this->dtExt($y, $jsd);
      }
      $v = $this->dtExt($y, $jsd);
      $dv = $this->dtExt($y0, $jsd) - $t0;
      return $v - $dv * ($y0 + 100 - $y) / 100;
    }
    for ($i = 0; $i < $size; $i += 5) {
      if ($y < Lunar::$DT_AT[$i + 5]) {
        break;
      }
    }
    $t1 = ($y - Lunar::$DT_AT[$i]) / (Lunar::$DT_AT[$i + 5] - Lunar::$DT_AT[$i]) * 10;
    $t2 = $t1 * $t1;
    $t3 = $t2 * $t1;
    return Lunar::$DT_AT[$i + 1] + Lunar::$DT_AT[$i + 2] * $t1 + Lunar::$DT_AT[$i + 3] * $t2 + Lunar::$DT_AT[$i + 4] * $t3;
  }

  private function dtT($t)
  {
    return $this->dtCalc($t / 365.2425 + 2000) / 86400.0;
  }

  private function saLonT($w)
  {
    $v = 628.3319653318;
    $t = ($w - 1.75347 - pi()) / $v;
    $v = $this->ev($t);
    $t += ($w - $this->saLon($t, 10)) / $v;
    $v = $this->ev($t);
    $t += ($w - $this->saLon($t, -1)) / $v;
    return $t;
  }

  private function qiLow($w)
  {
    $v = 628.3319653318;
    $t = ($w - 4.895062166) / $v;
    $t -= (53 * $t * $t + 334116 * cos(4.67 + 628.307585 * $t) + 2061 * cos(2.678 + 628.3076 * $t) * $t) / $v / 10000000;
    $l = 48950621.66 + 6283319653.318 * $t + 53 * $t * $t + 334166 * cos(4.669257 + 628.307585 * $t) + 3489 * cos(4.6261 + 1256.61517 * $t) + 2060.6 * cos(2.67823 + 628.307585 * $t) * $t - 994 - 834 * sin(2.1824 - 33.75705 * $t);
    $t -= ($l / 10000000 - $w) / 628.332 + (32 * ($t + 1.8) * ($t + 1.8) - 20) / 86400 / 36525;
    return $t * 36525 + 8 / 24;
  }

  private function saLonT2($w)
  {
    $pi = pi();
    $v = 628.3319653318;
    $t = ($w - 1.75347 - $pi) / $v;
    $t -= (0.000005297 * $t * $t + 0.0334166 * cos(4.669257 + 628.307585 * $t) + 0.0002061 * cos(2.67823 + 628.307585 * $t) * $t) / $v;
    $t += ($w - $this->eLon($t, 8) - $pi + (20.5 + 17.2 * sin(2.1824 - 33.75705 * $t)) / (180 * 3600 / $pi)) / $v;
    return $t;
  }

  private function qiHigh($w)
  {
    $t = $this->saLonT2($w) * 36525;
    $t = $t - $this->dtT($t) + 8 / 24;
    $v = (($t + 0.5) % 1) * 86400;
    if ($v < 1200 || $v > 86400 - 1200) {
      $t = $this->saLonT($w) * 36525 - $this->dtT($t) + 8 / 24;
    }
    return $t;
  }

  private function calcJieQi($jd)
  {
    $size = count(Lunar::$QI_KB);
    $d = 0;
    $pc = 7;
    $jd += 2451545;
    $f1 = Lunar::$QI_KB[0] - $pc;
    $f2 = Lunar::$QI_KB[$size - 1] - $pc;
    $f3 = 2436935;
    if ($jd < $f1 || $jd >= $f3) {
      $d = intval(floor($this->qiHigh(intval(floor(($jd + $pc - 2451259) * 24 / 365.2422)) * pi() / 12) + 0.5));
    } else if ($jd >= $f1 && $jd < $f2) {
      $i = 0;
      for (; $i < $size; $i += 2) {
        if ($jd + $pc < Lunar::$QI_KB[$i + 2]) {
          break;
        }
      }
      $d = Lunar::$QI_KB[$i] + Lunar::$QI_KB[$i + 1] * intval(floor(($jd + $pc - Lunar::$QI_KB[$i]) / Lunar::$QI_KB[$i + 1]));
      $d = intval(floor($d + 0.5));
      if ($d == 1683460) {
        $d++;
      }
      $d -= 2451545;
    } else if ($jd >= $f2 && $jd < $f3) {
      $d = intval(floor($this->qiLow(intval(floor(($jd + $pc - 2451259) * 24 / 365.2422)) * pi() / 12) + 0.5));
      $n = substr(Lunar::$QB, intval(floor(($jd - $f2) / 365.2422 * 24)), 1);
      if (strcmp('1', $n) == 0) {
        $d += 1;
      }
      if (strcmp('2', $n) == 0) {
        $d -= 1;
      }
    }
    return $d;
  }

  private function qiAccurate($w)
  {
    $t = $this->saLonT($w) * 36525;
    return $t - $this->dtT($t) + 8 / 24;
  }

  private function qiAccurate2($jd)
  {
    $d = pi() / 12;
    $w = intval(floor(($jd + 293) * 24 / 365.2422)) * $d;
    $a = $this->qiAccurate($w);
    if ($a - $jd > 5) {
      return $this->qiAccurate($w - $d);
    } else if ($a - $jd < -5) {
      return $this->qiAccurate($w + $d);
    }
    return $a;
  }

  /**
   * 计算节气表
   */
  private function computeJieQi()
  {
    $jd = intval(floor(($this->solar->getYear() - 2000) * 365.2422 + 180));
    $w = intval(floor(($jd - 355 + 183) / 365.2422)) * 365.2422 + 355;
    if ($this->calcJieQi($w) > $jd) {
      $w -= 365.2422;
    }
    //追加上一农历年末的大雪
    $q = $this->calcJieQi($w - 15.2184);
    $this->jieQi[Lunar::$JIE_QI_PREPEND] = Solar::fromJulianDay($this->qiAccurate2($q) + Solar::$J2000);
    $size = count(Lunar::$JIE_QI);
    for ($i = 0; $i < $size; $i++) {
      $q = $this->calcJieQi($w + 15.2184 * $i);
      $this->jieQi[Lunar::$JIE_QI[$i]] = Solar::fromJulianDay($this->qiAccurate2($q) + Solar::$J2000);
    }
    //追加下一农历年初的冬至
    $q = $this->calcJieQi($w + 15.2184 * $size);
    $this->jieQi[Lunar::$JIE_QI_APPEND] = Solar::fromJulianDay($this->qiAccurate2($q) + Solar::$J2000);

    //追加下一阳历年初的小寒
    $size++;
    $q = $this->calcJieQi($w + 15.2184 * $size);
    $this->jieQi[Lunar::$JIE_APPEND_SOLAR_FIRST] = Solar::fromJulianDay($this->qiAccurate2($q) + Solar::$J2000);

    //追加下一阳历年初的大寒
    $size++;
    $q = $this->calcJieQi($w + 15.2184 * $size);
    $this->jieQi[Lunar::$QI_APPEND_SOLAR_SECOND] = Solar::fromJulianDay($this->qiAccurate2($q) + Solar::$J2000);
  }

  /**
   * 计算干支纪年
   */
  private function computeYear()
  {
    //以正月初一开始
    $yearGanIndex = ($this->year + LunarUtil::$BASE_YEAR_GAN_ZHI_INDEX) % 10;
    $yearZhiIndex = ($this->year + LunarUtil::$BASE_YEAR_GAN_ZHI_INDEX) % 12;

    //以立春作为新一年的开始的干支纪年
    $g = $yearGanIndex;
    $z = $yearZhiIndex;

    //精确的干支纪年，以立春交接时刻为准
    $gExact = $yearGanIndex;
    $zExact = $yearZhiIndex;

    //获取立春的阳历时刻
    $liChun = $this->jieQi['立春'];

    //阳历和阴历年份相同代表正月初一及以后
    if ($this->year === $this->solar->getYear()) {
      //立春日期判断
      if (strcmp($this->solar->toYmd(), $liChun->toYmd()) < 0) {
        $g--;
        $z--;
      }
      //立春交接时刻判断
      if (strcmp($this->solar->toYmdHms(), $liChun->toYmdHms()) < 0) {
        $gExact--;
        $zExact--;
      }
    } else {
      if (strcmp($this->solar->toYmd(), $liChun->toYmd()) >= 0) {
        $g++;
        $z++;
      }
      if (strcmp($this->solar->toYmdHms(), $liChun->toYmdHms()) >= 0) {
        $gExact++;
        $zExact++;
      }
    }
    if ($g < 0) {
      $g += 10;
    }
    if ($g >= 10) {
      $g -= 10;
    }
    if ($z < 0) {
      $z += 12;
    }
    if ($z >= 12) {
      $z -= 12;
    }
    if ($gExact < 0) {
      $gExact += 10;
    }
    if ($gExact >= 10) {
      $gExact -= 10;
    }
    if ($zExact < 0) {
      $zExact += 12;
    }
    if ($zExact >= 12) {
      $zExact -= 12;
    }

    $this->yearGanIndex = $yearGanIndex;
    $this->yearZhiIndex = $yearZhiIndex;

    $this->yearGanIndexByLiChun = $g;
    $this->yearZhiIndexByLiChun = $z;

    $this->yearGanIndexExact = $gExact;
    $this->yearZhiIndexExact = $zExact;
  }

  /**
   * 干支纪月计算
   */
  private function computeMonth()
  {
    $start = null;
    //干偏移值（以立春当天起算）
    $gOffset = (($this->yearGanIndexByLiChun % 5 + 1) * 2) % 10;
    //干偏移值（以立春交接时刻起算）
    $gOffsetExact = (($this->yearGanIndexExact % 5 + 1) * 2) % 10;

    //序号：大雪到小寒之间-2，小寒到立春之间-1，立春之后0
    $index = -2;
    foreach (LunarUtil::$JIE as $jie) {
      $end = $this->jieQi[$jie];
      $ymd = $this->solar->toYmd();
      $symd = (null == $start) ? $ymd : $start->toYmd();
      $eymd = $end->toYmd();
      if (strcmp($ymd, $symd) >= 0 && strcmp($ymd, $eymd) < 0) {
        break;
      }
      $start = $end;
      $index++;
    }
    if ($index < 0) {
      $index += 12;
    }

    $this->monthGanIndex = ($index + $gOffset) % 10;
    $this->monthZhiIndex = ($index + LunarUtil::$BASE_MONTH_ZHI_INDEX) % 12;

    $start = null;
    //序号：大雪到小寒之间-2，小寒到立春之间-1，立春之后0
    $indexExact = -2;
    foreach (LunarUtil::$JIE as $jie) {
      $end = $this->jieQi[$jie];
      $time = $this->solar->toYmdHms();
      $stime = null == $start ? $time : $start->toYmdHms();
      $etime = $end->toYmdHms();
      if (strcmp($time, $stime) >= 0 && strcmp($time, $etime) < 0) {
        break;
      }
      $start = $end;
      $indexExact++;
    }
    if ($indexExact < 0) {
      $indexExact += 12;
    }
    $this->monthGanIndexExact = ($indexExact + $gOffsetExact) % 10;
    $this->monthZhiIndexExact = ($indexExact + LunarUtil::$BASE_MONTH_ZHI_INDEX) % 12;
  }

  /**
   * 干支纪日计算
   */
  private function computeDay()
  {
    $addDays = ($this->dayOffset + LunarUtil::$BASE_DAY_GAN_ZHI_INDEX) % 60;
    $dayGanIndex = $addDays % 10;
    $dayZhiIndex = $addDays % 12;

    $this->dayGanIndex = $dayGanIndex;
    $this->dayZhiIndex = $dayZhiIndex;

    $dayGanExact = $dayGanIndex;
    $dayZhiExact = $dayZhiIndex;

    $this->dayGanIndexExact2 = $dayGanExact;
    $this->dayZhiIndexExact2 = $dayZhiExact;

    $hm = ($this->hour < 10 ? '0' : '') . $this->hour . ':' . ($this->minute < 10 ? '0' : '') . $this->minute;
    if (strcmp($hm, '23:00') >= 0 && strcmp($hm, '23:59') <= 0) {
      $dayGanExact++;
      if ($dayGanExact >= 10) {
        $dayGanExact -= 10;
      }
      $dayZhiExact++;
      if ($dayZhiExact >= 12) {
        $dayZhiExact -= 12;
      }
    }

    $this->dayGanIndexExact = $dayGanExact;
    $this->dayZhiIndexExact = $dayZhiExact;
  }

  /**
   * 干支纪时计算
   */
  private function computeTime()
  {
    $this->timeZhiIndex = LunarUtil::getTimeZhiIndex(($this->hour < 10 ? '0' : '') . $this->hour . ':' . ($this->minute < 10 ? '0' : '') . $this->minute);
    $this->timeGanIndex = ($this->dayGanIndexExact % 5 * 2 + $this->timeZhiIndex) % 10;
  }

  /**
   * 星期计算
   */
  private function computeWeek()
  {
    $this->weekIndex = ($this->dayOffset + LunarUtil::$BASE_WEEK_INDEX) % 7;
  }

  private function compute()
  {
    $this->computeJieQi();
    $this->computeYear();
    $this->computeMonth();
    $this->computeDay();
    $this->computeTime();
    $this->computeWeek();
  }

  public function getYear()
  {
    return $this->year;
  }

  public function getMonth()
  {
    return $this->month;
  }

  public function getDay()
  {
    return $this->day;
  }

  public function getHour()
  {
    return $this->hour;
  }

  public function getMinute()
  {
    return $this->minute;
  }

  public function getSecond()
  {
    return $this->second;
  }

  public function getSolar()
  {
    return $this->solar;
  }

  /**
   * 获取年份的天干（以正月初一作为新年的开始）
   * @return string 天干，如辛
   */
  public function getYearGan()
  {
    return LunarUtil::$GAN[$this->yearGanIndex + 1];
  }

  /**
   * 获取年份的天干（以立春当天作为新年的开始）
   *
   * @return string 天干，如辛
   */
  public function getYearGanByLiChun()
  {
    return LunarUtil::$GAN[$this->yearGanIndexByLiChun + 1];
  }

  /**
   * 获取最精确的年份天干（以立春交接的时刻作为新年的开始）
   *
   * @return string 天干，如辛
   */
  public function getYearGanExact()
  {
    return LunarUtil::$GAN[$this->yearGanIndexExact + 1];
  }

  /**
   * 获取年份的地支（以正月初一作为新年的开始）
   *
   * @return string 地支，如亥
   */
  public function getYearZhi()
  {
    return LunarUtil::$ZHI[$this->yearZhiIndex + 1];
  }

  /**
   * 获取年份的地支（以立春当天作为新年的开始）
   *
   * @return string 地支，如亥
   */
  public function getYearZhiByLiChun()
  {
    return LunarUtil::$ZHI[$this->yearZhiIndexByLiChun + 1];
  }

  /**
   * 获取最精确的年份地支（以立春交接的时刻作为新年的开始）
   *
   * @return string 地支，如亥
   */
  public function getYearZhiExact()
  {
    return LunarUtil::$ZHI[$this->yearZhiIndexExact + 1];
  }

  /**
   * 获取干支纪年（年柱）（以正月初一作为新年的开始）
   * @return string 年份的干支（年柱），如辛亥
   */
  public function getYearInGanZhi()
  {
    return $this->getYearGan() . $this->getYearZhi();
  }

  /**
   * 获取干支纪年（年柱）（以立春当天作为新年的开始）
   * @return string 年份的干支（年柱），如辛亥
   */
  public function getYearInGanZhiByLiChun()
  {
    return $this->getYearGanByLiChun() . $this->getYearZhiByLiChun();
  }

  /**
   * 获取干支纪年（年柱）（以立春交接的时刻作为新年的开始）
   * @return string 年份的干支（年柱），如辛亥
   */
  public function getYearInGanZhiExact()
  {
    return $this->getYearGanExact() . $this->getYearZhiExact();
  }

  /**
   * 获取干支纪月（月柱）（以节交接当天起算）
   * <p>月天干口诀：甲己丙寅首，乙庚戊寅头。丙辛从庚寅，丁壬壬寅求，戊癸甲寅居，周而复始流。</p>
   * <p>月地支：正月起寅</p>
   *
   * @return string 干支纪月（月柱），如己卯
   */
  public function getMonthInGanZhi()
  {
    return $this->getMonthGan() . $this->getMonthZhi();
  }

  /**
   * 获取精确的干支纪月（月柱）（以节交接时刻起算）
   * <p>月天干口诀：甲己丙寅首，乙庚戊寅头。丙辛从庚寅，丁壬壬寅求，戊癸甲寅居，周而复始流。</p>
   * <p>月地支：正月起寅</p>
   *
   * @return string 干支纪月（月柱），如己卯
   */
  public function getMonthInGanZhiExact()
  {
    return $this->getMonthGanExact() . $this->getMonthZhiExact();
  }

  /**
   * 获取月天干（以节交接当天起算）
   * @return string 月天干，如己
   */
  public function getMonthGan()
  {
    return LunarUtil::$GAN[$this->monthGanIndex + 1];
  }

  /**
   * 获取精确的月天干（以节交接时刻起算）
   * @return string 月天干，如己
   */
  public function getMonthGanExact()
  {
    return LunarUtil::$GAN[$this->monthGanIndexExact + 1];
  }

  /**
   * 获取月地支（以节交接当天起算）
   * @return string 月地支，如卯
   */
  public function getMonthZhi()
  {
    return LunarUtil::$ZHI[$this->monthZhiIndex + 1];
  }

  /**
   * 获取精确的月地支（以节交接时刻起算）
   * @return string 月地支，如卯
   */
  public function getMonthZhiExact()
  {
    return LunarUtil::$ZHI[$this->monthZhiIndexExact + 1];
  }

  /**
   * 获取干支纪日（日柱）
   *
   * @return string 干支纪日（日柱），如己卯
   */
  public function getDayInGanZhi()
  {
    return $this->getDayGan() . $this->getDayZhi();
  }

  /**
   * 获取干支纪日（日柱，八字流派1，晚子时日柱算明天）
   * @return string 干支纪日（日柱），如己卯
   */
  public function getDayInGanZhiExact()
  {
    return $this->getDayGanExact() . $this->getDayZhiExact();
  }

  /**
   * 获取干支纪日（日柱，八字流派2，晚子时日柱算当天）
   * @return string 干支纪日（日柱），如己卯
   */
  public function getDayInGanZhiExact2()
  {
    return $this->getDayGanExact2() . $this->getDayZhiExact2();
  }

  /**
   * 获取日天干
   *
   * @return string 日天干，如甲
   */
  public function getDayGan()
  {
    return LunarUtil::$GAN[$this->dayGanIndex + 1];
  }

  /**
   * 获取日天干（八字流派1，晚子时日柱算明天）
   * @return string 日天干，如甲
   */
  public function getDayGanExact()
  {
    return LunarUtil::$GAN[$this->dayGanIndexExact + 1];
  }

  /**
   * 获取日天干（八字流派1，晚子时日柱算当天）
   * @return string 日天干，如甲
   */
  public function getDayGanExact2()
  {
    return LunarUtil::$GAN[$this->dayGanIndexExact2 + 1];
  }

  /**
   * 获取日地支
   *
   * @return string 日地支，如卯
   */
  public function getDayZhi()
  {
    return LunarUtil::$ZHI[$this->dayZhiIndex + 1];
  }

  /**
   * 获取日地支（八字流派1，晚子时日柱算明天）
   * @return string 日地支，如卯
   */
  public function getDayZhiExact()
  {
    return LunarUtil::$ZHI[$this->dayZhiIndexExact + 1];
  }

  /**
   * 获取日地支（八字流派1，晚子时日柱算当天）
   * @return string 日地支，如卯
   */
  public function getDayZhiExact2()
  {
    return LunarUtil::$ZHI[$this->dayZhiIndexExact2 + 1];
  }

  /**
   * 获取年生肖（以正月初一起算）
   *
   * @return string 年生肖，如虎
   */
  public function getYearShengXiao()
  {
    return LunarUtil::$SHENG_XIAO[$this->yearZhiIndex + 1];
  }

  /**
   * 获取年生肖（以立春当天起算）
   *
   * @return string 年生肖，如虎
   */
  public function getYearShengXiaoByLiChun()
  {
    return LunarUtil::$SHENG_XIAO[$this->yearZhiIndexByLiChun + 1];
  }

  /**
   * 获取精确的年生肖（以立春交接时刻起算）
   *
   * @return string 年生肖，如虎
   */
  public function getYearShengXiaoExact()
  {
    return LunarUtil::$SHENG_XIAO[$this->yearZhiIndexExact + 1];
  }

  /**
   * 获取月生肖
   *
   * @return string 月生肖，如虎
   */
  public function getMonthShengXiao()
  {
    return LunarUtil::$SHENG_XIAO[$this->monthZhiIndex + 1];
  }

  /**
   * 获取日生肖
   *
   * @return string 日生肖，如虎
   */
  public function getDayShengXiao()
  {
    return LunarUtil::$SHENG_XIAO[$this->dayZhiIndex + 1];
  }

  /**
   * 获取时辰生肖
   *
   * @return string 时辰生肖，如虎
   */
  public function getTimeShengXiao()
  {
    return LunarUtil::$SHENG_XIAO[$this->timeZhiIndex + 1];
  }

  /**
   * 获取中文的年
   *
   * @return string 中文年，如二零零一
   */
  public function getYearInChinese()
  {
    $y = ($this->year . '');
    $s = '';
    for ($i = 0, $j = strlen($y); $i < $j; $i++) {
      $s .= LunarUtil::$NUMBER[ord(substr($y, $i, 1)) - 48];
    }
    return $s;
  }

  /**
   * 获取中文的月
   *
   * @return string 中文月，如正
   */
  public function getMonthInChinese()
  {
    return ($this->month < 0 ? '闰' : '') . LunarUtil::$MONTH[abs($this->month)];
  }

  /**
   * 获取中文日
   *
   * @return string 中文日，如初一
   */
  public function getDayInChinese()
  {
    return LunarUtil::$DAY[$this->day];
  }

  /**
   * 获取时辰（地支）
   * @return string 时辰（地支）
   */
  public function getTimeZhi()
  {
    return LunarUtil::$ZHI[$this->timeZhiIndex + 1];
  }

  /**
   * 获取时辰（天干）
   * @return string 时辰（天干）
   */
  public function getTimeGan()
  {
    return LunarUtil::$GAN[$this->timeGanIndex + 1];
  }

  /**
   * 获取时辰干支（时柱）
   * @return string 时辰干支（时柱）
   */
  public function getTimeInGanZhi()
  {
    return $this->getTimeGan() . $this->getTimeZhi();
  }

  /**
   * 获取季节
   * @return string 农历季节
   */
  public function getSeason()
  {
    return LunarUtil::$SEASON[abs($this->month)];
  }

  /**
   * 获取节
   *
   * @return string 节
   */
  public function getJie()
  {
    foreach (LunarUtil::$JIE as $jie) {
      $d = $this->jieQi[$jie];
      if ($d->getYear() === $this->solar->getYear() && $d->getMonth() === $this->solar->getMonth() && $d->getDay() === $this->solar->getDay()) {
        return $jie;
      }
    }
    $d = $this->jieQi[Lunar::$JIE_QI_PREPEND];
    if ($d->getYear() === $this->solar->getYear() && $d->getMonth() === $this->solar->getMonth() && $d->getDay() === $this->solar->getDay()) {
      return Lunar::$JIE_QI_LAST;
    }
    $d = $this->jieQi[Lunar::$JIE_APPEND_SOLAR_FIRST];
    if ($d->getYear() === $this->solar->getYear() && $d->getMonth() === $this->solar->getMonth() && $d->getDay() === $this->solar->getDay()) {
      return Lunar::$JIE_SOLAR_FIRST;
    }
    return '';
  }

  /**
   * 获取气
   *
   * @return string 气
   */
  public function getQi()
  {
    foreach (LunarUtil::$QI as $qi) {
      $d = $this->jieQi[$qi];
      if ($d->getYear() === $this->solar->getYear() && $d->getMonth() === $this->solar->getMonth() && $d->getDay() === $this->solar->getDay()) {
        return $qi;
      }
    }
    $d = $this->jieQi[Lunar::$JIE_QI_APPEND];
    if ($d->getYear() === $this->solar->getYear() && $d->getMonth() === $this->solar->getMonth() && $d->getDay() === $this->solar->getDay()) {
      return Lunar::$JIE_QI_FIRST;
    }
    $d = $this->jieQi[Lunar::$QI_APPEND_SOLAR_SECOND];
    if ($d->getYear() === $this->solar->getYear() && $d->getMonth() === $this->solar->getMonth() && $d->getDay() === $this->solar->getDay()) {
      return Lunar::$QI_SOLAR_SECOND;
    }
    return '';
  }

  /**
   * 获取星期，0代表周日，1代表周一
   *
   * @return int 0123456
   */
  public function getWeek()
  {
    return $this->weekIndex;
  }

  /**
   * 获取星期的中文
   *
   * @return string 日一二三四五六
   */
  public function getWeekInChinese()
  {
    return SolarUtil::$WEEK[$this->getWeek()];
  }

  /**
   * 获取宿
   *
   * @return string 宿
   */
  public function getXiu()
  {
    return LunarUtil::$XIU[$this->getDayZhi() . $this->getWeek()];
  }

  /**
   * 获取宿吉凶
   *
   * @return string 吉/凶
   */
  public function getXiuLuck()
  {
    return LunarUtil::$XIU_LUCK[$this->getXiu()];
  }

  /**
   * 获取宿歌诀
   *
   * @return string 宿歌诀
   */
  public function getXiuSong()
  {
    return LunarUtil::$XIU_SONG[$this->getXiu()];
  }

  /**
   * 获取政
   *
   * @return string 政
   */
  public function getZheng()
  {
    return LunarUtil::$ZHENG[$this->getXiu()];
  }

  /**
   * 获取动物
   * @return string 动物
   */
  public function getAnimal()
  {
    return LunarUtil::$ANIMAL[$this->getXiu()];
  }

  /**
   * 获取宫
   * @return string 宫
   */
  public function getGong()
  {
    return LunarUtil::$GONG[$this->getXiu()];
  }

  /**
   * 获取兽
   * @return string 兽
   */
  public function getShou()
  {
    return LunarUtil::$SHOU[$this->getGong()];
  }

  /**
   * 获取节日，有可能一天会有多个节日
   *
   * @return array 节日列表，如春节
   */
  public function getFestivals()
  {
    $l = array();
    if (!empty(LunarUtil::$FESTIVAL[$this->month . '-' . $this->day])) {
      $l[] = LunarUtil::$FESTIVAL[$this->month . '-' . $this->day];
    }
    return $l;
  }

  /**
   * 获取非正式的节日，有可能一天会有多个节日
   *
   * @return array 非正式的节日列表，如中元节
   */
  public function getOtherFestivals()
  {
    $l = array();
    if (!empty(LunarUtil::$OTHER_FESTIVAL[$this->month . '-' . $this->day])) {
      $l[] = LunarUtil::$OTHER_FESTIVAL[$this->month . '-' . $this->day];
    }
    return $l;
  }

  /**
   * 获取彭祖百忌天干
   * @return string 彭祖百忌天干
   */
  public function getPengZuGan()
  {
    return LunarUtil::$PENG_ZU_GAN[$this->dayGanIndex + 1];
  }

  /**
   * 获取彭祖百忌地支
   * @return string 彭祖百忌地支
   */
  public function getPengZuZhi()
  {
    return LunarUtil::$PENG_ZU_ZHI[$this->dayZhiIndex + 1];
  }

  /**
   * 获取日喜神方位
   * @return string 喜神方位，如艮
   */
  public function getPositionXi()
  {
    return $this->getDayPositionXi();
  }

  /**
   * 获取日喜神方位描述
   * @return string 喜神方位描述，如东北
   */
  public function getPositionXiDesc()
  {
    return $this->getDayPositionXiDesc();
  }

  /**
   * 获取日喜神方位
   * @return string 喜神方位，如艮
   */
  public function getDayPositionXi()
  {
    return LunarUtil::$POSITION_XI[$this->dayGanIndex + 1];
  }

  /**
   * 获取日喜神方位描述
   * @return string 喜神方位描述，如东北
   */
  public function getDayPositionXiDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getDayPositionXi()];
  }

  /**
   * 获取时辰喜神方位
   * @return string 喜神方位，如艮
   */
  public function getTimePositionXi()
  {
    return LunarUtil::$POSITION_XI[$this->timeGanIndex + 1];
  }

  /**
   * 获取时辰喜神方位描述
   * @return string 喜神方位描述，如东北
   */
  public function getTimePositionXiDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getTimePositionXi()];
  }

  /**
   * 获取日阳贵神方位
   * @return string 阳贵神方位，如艮
   */
  public function getPositionYangGui()
  {
    return $this->getDayPositionYangGui();
  }

  /**
   * 获取日阳贵神方位描述
   * @return string 阳贵神方位描述，如东北
   */
  public function getPositionYangGuiDesc()
  {
    return $this->getDayPositionYangGuiDesc();
  }

  /**
   * 获取日阳贵神方位
   * @return string 阳贵神方位，如艮
   */
  public function getDayPositionYangGui()
  {
    return LunarUtil::$POSITION_YANG_GUI[$this->dayGanIndex + 1];
  }

  /**
   * 获取日阳贵神方位描述
   * @return string 阳贵神方位描述，如东北
   */
  public function getDayPositionYangGuiDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getDayPositionYangGui()];
  }

  /**
   * 获取时辰阳贵神方位
   * @return string 阳贵神方位，如艮
   */
  public function getTimePositionYangGui()
  {
    return LunarUtil::$POSITION_YANG_GUI[$this->timeGanIndex + 1];
  }

  /**
   * 获取时辰阳贵神方位描述
   * @return string 阳贵神方位描述，如东北
   */
  public function getTimePositionYangGuiDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getTimePositionYangGui()];
  }

  /**
   * 获取日阴贵神方位
   * @return string 阴贵神方位，如艮
   */
  public function getPositionYinGui()
  {
    return $this->getDayPositionYinGui();
  }

  /**
   * 获取日阴贵神方位描述
   * @return string 阴贵神方位描述，如东北
   */
  public function getPositionYinGuiDesc()
  {
    return $this->getDayPositionYinGuiDesc();
  }

  /**
   * 获取日阴贵神方位
   * @return string 阴贵神方位，如艮
   */
  public function getDayPositionYinGui()
  {
    return LunarUtil::$POSITION_YIN_GUI[$this->dayGanIndex + 1];
  }

  /**
   * 获取日阴贵神方位描述
   * @return string 阴贵神方位描述，如东北
   */
  public function getDayPositionYinGuiDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getDayPositionYinGui()];
  }

  /**
   * 获取时辰阴贵神方位
   * @return string 阴贵神方位，如艮
   */
  public function getTimePositionYinGui()
  {
    return LunarUtil::$POSITION_YIN_GUI[$this->timeGanIndex + 1];
  }

  /**
   * 获取时辰阴贵神方位描述
   * @return string 阴贵神方位描述，如东北
   */
  public function getTimePositionYinGuiDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getTimePositionYinGui()];
  }

  /**
   * 获取日福神方位
   * @return string 福神方位，如艮
   */
  public function getPositionFu()
  {
    return $this->getDayPositionFu();
  }

  /**
   * 获取日福神方位描述
   * @return string 福神方位描述，如东北
   */
  public function getPositionFuDesc()
  {
    return $this->getDayPositionFuDesc();
  }

  /**
   * 获取日福神方位
   * @return string 福神方位，如艮
   */
  public function getDayPositionFu()
  {
    return LunarUtil::$POSITION_FU[$this->dayGanIndex + 1];
  }

  /**
   * 获取日福神方位描述
   * @return string 福神方位描述，如东北
   */
  public function getDayPositionFuDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getDayPositionFu()];
  }

  /**
   * 获取时辰福神方位
   * @return string 福神方位，如艮
   */
  public function getTimePositionFu()
  {
    return LunarUtil::$POSITION_FU[$this->timeGanIndex + 1];
  }

  /**
   * 获取时辰福神方位描述
   * @return string 福神方位描述，如东北
   */
  public function getTimePositionFuDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getTimePositionFu()];
  }

  /**
   * 获取日财神方位
   * @return string 财神方位，如艮
   */
  public function getPositionCai()
  {
    return $this->getDayPositionCai();
  }

  /**
   * 获取日财神方位描述
   * @return string 财神方位描述，如东北
   */
  public function getPositionCaiDesc()
  {
    return $this->getDayPositionCaiDesc();
  }

  /**
   * 获取日财神方位
   * @return string 财神方位，如艮
   */
  public function getDayPositionCai()
  {
    return LunarUtil::$POSITION_CAI[$this->dayGanIndex + 1];
  }

  /**
   * 获取日财神方位描述
   * @return string 财神方位描述，如东北
   */
  public function getDayPositionCaiDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getDayPositionCai()];
  }

  /**
   * 获取时辰财神方位
   * @return string 财神方位，如艮
   */
  public function getTimePositionCai()
  {
    return LunarUtil::$POSITION_CAI[$this->timeGanIndex + 1];
  }

  /**
   * 获取时辰财神方位描述
   * @return string 财神方位描述，如东北
   */
  public function getTimePositionCaiDesc()
  {
    return LunarUtil::$POSITION_DESC[$this->getTimePositionCai()];
  }

  /**
   * 获取冲
   * @return string 冲，如申
   */
  public function getChong()
  {
    return $this->getDayChong();
  }

  /**
   * 获取日冲
   * @return string 日冲，如申
   */
  public function getDayChong()
  {
    return LunarUtil::$CHONG[$this->dayZhiIndex + 1];
  }

  /**
   * 获取时冲
   * @return string 时冲，如申
   */
  public function getTimeChong()
  {
    return LunarUtil::$CHONG[$this->timeZhiIndex + 1];
  }

  /**
   * 获取无情之克的冲天干
   * @return string 无情之克的冲天干，如甲
   */
  public function getChongGan()
  {
    return $this->getDayChongGan();
  }

  /**
   * 获取无情之克的日冲天干
   * @return string 无情之克的日冲天干，如甲
   */
  public function getDayChongGan()
  {
    return LunarUtil::$CHONG_GAN[$this->dayGanIndex + 1];
  }

  /**
   * 获取无情之克的时冲天干
   * @return string 无情之克的时冲天干，如甲
   */
  public function getTimeChongGan()
  {
    return LunarUtil::$CHONG_GAN[$this->timeGanIndex + 1];
  }

  /**
   * 获取有情之克的冲天干
   * @return string 有情之克的冲天干，如甲
   */
  public function getChongGanTie()
  {
    return $this->getDayChongGanTie();
  }

  /**
   * 获取有情之克的日冲天干
   * @return string 有情之克的日冲天干，如甲
   */
  public function getDayChongGanTie()
  {
    return LunarUtil::$CHONG_GAN_TIE[$this->dayGanIndex + 1];
  }

  /**
   * 获取有情之克的时冲天干
   * @return string 有情之克的时冲天干，如甲
   */
  public function getTimeChongGanTie()
  {
    return LunarUtil::$CHONG_GAN_TIE[$this->timeGanIndex + 1];
  }

  /**
   * 获取冲生肖
   * @return string 冲生肖，如猴
   */
  public function getChongShengXiao()
  {
    return $this->getDayChongShengXiao();
  }

  /**
   * 获取日冲生肖
   * @return string 日冲生肖，如猴
   */
  public function getDayChongShengXiao()
  {
    $chong = $this->getDayChong();
    for ($i = 0, $j = count(LunarUtil::$ZHI); $i < $j; $i++) {
      if (strcmp(LunarUtil::$ZHI[$i], $chong) === 0) {
        return LunarUtil::$SHENG_XIAO[$i];
      }
    }
    return '';
  }

  /**
   * 获取时冲生肖
   * @return string 时冲生肖，如猴
   */
  public function getTimeChongShengXiao()
  {
    $chong = $this->getTimeChong();
    for ($i = 0, $j = count(LunarUtil::$ZHI); $i < $j; $i++) {
      if (strcmp(LunarUtil::$ZHI[$i], $chong) === 0) {
        return LunarUtil::$SHENG_XIAO[$i];
      }
    }
    return '';
  }

  /**
   * 获取冲描述
   * @return string 冲描述，如(壬申)猴
   */
  public function getChongDesc()
  {
    return $this->getDayChongDesc();
  }

  /**
   * 获取日冲描述
   * @return string 日冲描述，如(壬申)猴
   */
  public function getDayChongDesc()
  {
    return '(' . $this->getDayChongGan() . $this->getDayChong() . ')' . $this->getDayChongShengXiao();
  }

  /**
   * 获取时冲描述
   * @return string 时冲描述，如(壬申)猴
   */
  public function getTimeChongDesc()
  {
    return '(' . $this->getTimeChongGan() . $this->getTimeChong() . ')' . $this->getTimeChongShengXiao();
  }

  /**
   * 获取煞
   * @return string 煞，如北
   */
  public function getSha()
  {
    return $this->getDaySha();
  }

  /**
   * 获取日煞
   * @return string 日煞，如北
   */
  public function getDaySha()
  {
    return LunarUtil::$SHA[$this->getDayZhi()];
  }

  /**
   * 获取时煞
   * @return string 时煞，如北
   */
  public function getTimeSha()
  {
    return LunarUtil::$SHA[$this->getTimeZhi()];
  }

  /**
   * 获取年纳音
   * @return string 年纳音，如剑锋金
   */
  public function getYearNaYin()
  {
    return LunarUtil::$NAYIN[$this->getYearInGanZhi()];
  }

  /**
   * 获取月纳音
   * @return string 月纳音，如剑锋金
   */
  public function getMonthNaYin()
  {
    return LunarUtil::$NAYIN[$this->getMonthInGanZhi()];
  }

  /**
   * 获取日纳音
   * @return string 日纳音，如剑锋金
   */
  public function getDayNaYin()
  {
    return LunarUtil::$NAYIN[$this->getDayInGanZhi()];
  }

  /**
   * 获取时辰纳音
   * @return string 时辰纳音，如剑锋金
   */
  public function getTimeNaYin()
  {
    return LunarUtil::$NAYIN[$this->getTimeInGanZhi()];
  }

  /**
   * 获取八字，男性也称乾造，女性也称坤造（以立春交接时刻作为新年的开始）
   * @return array 八字（男性也称乾造，女性也称坤造）
   */
  public function getBaZi()
  {
    $baZi = $this->getEightChar();
    $l = array();
    $l[] = $baZi->getYear();
    $l[] = $baZi->getMonth();
    $l[] = $baZi->getDay();
    $l[] = $baZi->getTime();
    return $l;
  }

  /**
   * 获取八字五行
   * @return array 八字五行
   */
  public function getBaZiWuXing()
  {
    $baZi = $this->getEightChar();
    $l = array();
    $l[] = $baZi->getYearWuXing();
    $l[] = $baZi->getMonthWuXing();
    $l[] = $baZi->getDayWuXing();
    $l[] = $baZi->getTimeWuXing();
    return $l;
  }

  /**
   * 获取八字纳音
   * @return array 八字纳音
   */
  public function getBaZiNaYin()
  {
    $baZi = $this->getEightChar();
    $l = array();
    $l[] = $baZi->getYearNaYin();
    $l[] = $baZi->getMonthNaYin();
    $l[] = $baZi->getDayNaYin();
    $l[] = $baZi->getTimeNaYin();
    return $l;
  }

  /**
   * 获取八字天干十神，日柱十神为日主，其余三柱根据天干十神表查询
   * @return array 八字天干十神
   */
  public function getBaZiShiShenGan()
  {
    $baZi = $this->getEightChar();
    $l = array();
    $l[] = $baZi->getYearShiShenGan();
    $l[] = $baZi->getMonthShiShenGan();
    $l[] = $baZi->getDayShiShenGan();
    $l[] = $baZi->getTimeShiShenGan();
    return $l;
  }

  /**
   * 获取八字地支十神，根据地支十神表查询
   * @return array 八字地支十神
   */
  public function getBaZiShiShenZhi()
  {
    $baZi = $this->getEightChar();
    $yearShiShenZhi = $baZi->getYearShiShenZhi();
    $monthShiShenZhi = $baZi->getMonthShiShenZhi();
    $dayShiShenZhi = $baZi->getDayShiShenZhi();
    $timeShiShenZhi = $baZi->getTimeShiShenZhi();
    $l = array();
    $l[] = $yearShiShenZhi[0];
    $l[] = $monthShiShenZhi[0];
    $l[] = $dayShiShenZhi[0];
    $l[] = $timeShiShenZhi[0];
    return $l;
  }

  /**
   * 获取八字年支十神
   * @return array 八字年支十神
   */
  public function getBaZiShiShenYearZhi()
  {
    return $this->getEightChar()->getYearShiShenZhi();
  }

  /**
   * 获取八字月支十神
   * @return array 八字月支十神
   */
  public function getBaZiShiShenMonthZhi()
  {
    return $this->getEightChar()->getMonthShiShenZhi();
  }

  /**
   * 获取八字日支十神
   * @return array 八字日支十神
   */
  public function getBaZiShiShenDayZhi()
  {
    return $this->getEightChar()->getDayShiShenZhi();
  }

  /**
   * 获取八字时支十神
   * @return array 八字时支十神
   */
  public function getBaZiShiShenTimeZhi()
  {
    return $this->getEightChar()->getTimeShiShenZhi();
  }

  /**
   * 获取十二执星：建、除、满、平、定、执、破、危、成、收、开、闭。当月支与日支相同即为建，依次类推
   * @return string 执星
   */
  public function getZhiXing()
  {
    $offset = $this->dayZhiIndex - $this->monthZhiIndex;
    if ($offset < 0) {
      $offset += 12;
    }
    return LunarUtil::$ZHI_XING[$offset + 1];
  }

  /**
   * 获取值日天神
   * @return string 值日天神
   */
  public function getDayTianShen()
  {
    $monthZhi = $this->getMonthZhi();
    $offset = LunarUtil::$ZHI_TIAN_SHEN_OFFSET[$monthZhi];
    return LunarUtil::$TIAN_SHEN[($this->dayZhiIndex + $offset) % 12 + 1];
  }

  /**
   * 获取值时天神
   * @return string 值时天神
   */
  public function getTimeTianShen()
  {
    $dayZhi = $this->getDayZhiExact();
    $offset = LunarUtil::$ZHI_TIAN_SHEN_OFFSET[$dayZhi];
    return LunarUtil::$TIAN_SHEN[($this->timeZhiIndex + $offset) % 12 + 1];
  }

  /**
   * 获取值日天神类型：黄道/黑道
   * @return string 值日天神类型：黄道/黑道
   */
  public function getDayTianShenType()
  {
    return LunarUtil::$TIAN_SHEN_TYPE[$this->getDayTianShen()];
  }

  /**
   * 获取值时天神类型：黄道/黑道
   * @return string 值时天神类型：黄道/黑道
   */
  public function getTimeTianShenType()
  {
    return LunarUtil::$TIAN_SHEN_TYPE[$this->getTimeTianShen()];
  }

  /**
   * 获取值日天神吉凶
   * @return string 吉/凶
   */
  public function getDayTianShenLuck()
  {
    return LunarUtil::$TIAN_SHEN_TYPE_LUCK[$this->getDayTianShenType()];
  }

  /**
   * 获取值时天神吉凶
   * @return string 吉/凶
   */
  public function getTimeTianShenLuck()
  {
    return LunarUtil::$TIAN_SHEN_TYPE_LUCK[$this->getTimeTianShenType()];
  }

  /**
   * 获取逐日胎神方位
   * @return string 逐日胎神方位
   */
  public function getDayPositionTai()
  {
    $offset = $this->dayGanIndex - $this->dayZhiIndex;
    if ($offset < 0) {
      $offset += 12;
    }
    return LunarUtil::$POSITION_TAI_DAY[$offset * 5 + $this->dayGanIndex];
  }

  /**
   * 获取逐月胎神方位，闰月无
   * @return string 逐月胎神方位
   */
  public function getMonthPositionTai()
  {
    if ($this->month < 0) {
      return '';
    }
    return LunarUtil::$POSITION_TAI_MONTH[$this->month - 1];
  }

  /**
   * 获取每日宜
   * @return array 宜
   */
  public function getDayYi()
  {
    return LunarUtil::getDayYi($this->getMonthInGanZhiExact(), $this->getDayInGanZhi());
  }

  /**
   * 获取时宜
   * @return array 宜
   */
  public function getTimeYi()
  {
    return LunarUtil::getTimeYi($this->getDayInGanZhiExact(), $this->getTimeInGanZhi());
  }

  /**
   * 获取每日忌
   * @return array 忌
   */
  public function getDayJi()
  {
    return LunarUtil::getDayJi($this->getMonthInGanZhiExact(), $this->getDayInGanZhi());
  }

  /**
   * 获取时忌
   * @return array 忌
   */
  public function getTimeJi()
  {
    return LunarUtil::getTimeJi($this->getDayInGanZhiExact(), $this->getTimeInGanZhi());
  }

  /**
   * 获取日吉神（宜趋），如果没有，返回['无']
   * @return array 吉神
   */
  public function getDayJiShen()
  {
    return LunarUtil::getDayJiShen($this->getMonth(), $this->getDayInGanZhi());
  }

  /**
   * 获取日凶煞（宜忌），如果没有，返回['无']
   * @return array 凶煞
   */
  public function getDayXiongSha()
  {
    return LunarUtil::getDayXiongSha($this->getMonth(), $this->getDayInGanZhi());
  }

  /**
   * 获取月相
   * @return string 月相
   */
  public function getYueXiang()
  {
    return LunarUtil::$YUE_XIANG[$this->getDay()];
  }

  /**
   * 获取值年九星（流年紫白星起例歌诀：年上吉星论甲子，逐年星逆中宫起；上中下作三元汇，一上四中七下兑。）
   * @return NineStar 值年九星
   */
  public function getYearNineStar()
  {
    $index = LunarUtil::$BASE_YEAR_JIU_XING_INDEX - ($this->getYear() - LunarUtil::$BASE_YEAR) % 9;
    if ($index < 0) {
      $index += 9;
    }
    return new NineStar($index);
  }

  /**
   * 获取值月九星（月紫白星歌诀：子午卯酉八白起，寅申巳亥二黑求，辰戌丑未五黄中。）
   * @return NineStar 值月九星
   */
  public function getMonthNineStar()
  {
    $start = 2;
    $yearZhi = $this->getYearZhi();
    if (strpos('子午卯酉', $yearZhi) !== false) {
      $start = 8;
    } else if (strpos('辰戌丑未', $yearZhi) !== false) {
      $start = 5;
    }
    // 寅月起，所以需要-2
    $monthIndex = $this->monthZhiIndex - 2;
    if ($monthIndex < 0) {
      $monthIndex += 12;
    }
    $index = $start - $monthIndex - 1;
    while ($index < 0) {
      $index += 9;
    }
    return new NineStar($index);
  }

  /**
   * 获取值日九星（日家紫白星歌诀：日家白法不难求，二十四气六宫周；冬至雨水及谷雨，阳顺一七四中游；夏至处暑霜降后，九三六星逆行求。）
   * @return NineStar 值日九星
   */
  public function getDayNineStar()
  {
    //顺逆
    $solarYmd = $this->solar->toYmd();
    $yuShui = $this->jieQi['雨水']->toYmd();
    $guYu = $this->jieQi['谷雨']->toYmd();
    $xiaZhi = $this->jieQi['夏至']->toYmd();
    $chuShu = $this->jieQi['处暑']->toYmd();
    $shuangJiang = $this->jieQi['霜降']->toYmd();

    $start = 6;
    $asc = false;
    if (strcmp($solarYmd, $this->jieQi['冬至']->toYmd()) >= 0 && strcmp($solarYmd, $yuShui) < 0) {
      $asc = true;
      $start = 1;
    } else if (strcmp($solarYmd, $yuShui) >= 0 && strcmp($solarYmd, $guYu) < 0) {
      $asc = true;
      $start = 7;
    } else if (strcmp($solarYmd, $guYu) >= 0 && strcmp($solarYmd, $xiaZhi) < 0) {
      $asc = true;
      $start = 4;
    } else if (strcmp($solarYmd, $xiaZhi) >= 0 && strcmp($solarYmd, $chuShu) < 0) {
      $start = 9;
    } else if (strcmp($solarYmd, $chuShu) >= 0 && strcmp($solarYmd, $shuangJiang) < 0) {
      $start = 3;
    }
    $ganZhiIndex = LunarUtil::getJiaZiIndex($this->getDayInGanZhi()) % 9;
    $index = $asc ? $start + $ganZhiIndex - 1 : $start - $ganZhiIndex - 1;
    if ($index > 8) {
      $index -= 9;
    }
    if ($index < 0) {
      $index += 9;
    }
    return new NineStar($index);
  }

  /**
   * 获取值时九星（时家紫白星歌诀：三元时白最为佳，冬至阳生顺莫差，孟日七宫仲一白，季日四绿发萌芽，每把时辰起甲子，本时星耀照光华，时星移入中宫去，顺飞八方逐细查。夏至阴生逆回首，孟归三碧季加六，仲在九宫时起甲，依然掌中逆轮跨。）
   * @return NineStar 值时九星
   */
  public function getTimeNineStar()
  {
    //顺逆
    $solarYmd = $this->solar->toYmd();
    $asc = false;
    if (strcmp($solarYmd, $this->jieQi['冬至']->toYmd()) >= 0 && strcmp($solarYmd, $this->jieQi['夏至']->toYmd()) < 0) {
      $asc = true;
    }
    $start = $asc ? 7 : 3;
    $dayZhi = $this->getDayZhi();
    if (strpos('子午卯酉', $dayZhi) !== false) {
      $start = $asc ? 1 : 9;
    } else if (strpos('辰戌丑未', $dayZhi) !== false) {
      $start = $asc ? 4 : 6;
    }
    $index = $asc ? $start + $this->timeZhiIndex - 1 : $start - $this->timeZhiIndex - 1;
    if ($index > 8) {
      $index -= 9;
    }
    if ($index < 0) {
      $index += 9;
    }
    return new NineStar($index);
  }

  /**
   * 获取节气表（节气名称:阳历），节气交接时刻精确到秒，以冬至开头，按先后顺序排列
   * @return Solar[] 节气表
   */
  public function getJieQiTable()
  {
    return $this->jieQi;
  }

  /**
   * 获取最近的节气，如果未找到匹配的，返回null
   * @param $forward bool 是否顺推，true为顺推，false为逆推
   * @param $conditions array|null 过滤条件，如果设置过滤条件，仅返回匹配该名称的
   * @return JieQi|null 节气
   */
  protected function getNearJieQi($forward, $conditions)
  {
    $name = null;
    $near = null;
    $filter = null != $conditions && count($conditions) > 0;
    $today = $this->solar->toYmdHms();
    foreach ($this->jieQi as $jq => $solar) {
      if (Lunar::$JIE_QI_APPEND == $jq) {
        $jq = Lunar::$JIE_QI_FIRST;
      }
      if (Lunar::$JIE_QI_PREPEND == $jq) {
        $jq = Lunar::$JIE_QI_LAST;
      }
      if (Lunar::$JIE_APPEND_SOLAR_FIRST == $jq) {
        $jq = Lunar::$JIE_SOLAR_FIRST;
      }
      if (Lunar::$QI_APPEND_SOLAR_SECOND == $jq) {
        $jq = Lunar::$QI_SOLAR_SECOND;
      }
      if ($filter) {
        if (!in_array($jq, $conditions)) {
          continue;
        }
      }
      $day = $solar->toYmdHms();
      if ($forward) {
        if (strcmp($day, $today) < 0) {
          continue;
        }
        if (null == $near || strcmp($day, $near) < 0) {
          $name = $jq;
          $near = $solar;
        }
      } else {
        if (strcmp($day, $today) > 0) {
          continue;
        }
        if (null == $near || strcmp($day, $near) > 0) {
          $name = $jq;
          $near = $solar;
        }
      }
    }
    if (null == $near) {
      return null;
    }
    return new JieQi($name, $near);
  }

  /**
   * 获取下一节（顺推的第一个节）
   * @return JieQi|null 节气
   */
  public function getNextJie()
  {
    return $this->getNearJieQi(true, LunarUtil::$JIE);
  }

  /**
   * 获取上一节（逆推的第一个节）
   * @return JieQi|null 节气
   */
  public function getPrevJie()
  {
    return $this->getNearJieQi(false, LunarUtil::$JIE);
  }

  /**
   * 获取下一气令（顺推的第一个气令）
   * @return JieQi|null 节气
   */
  public function getNextQi()
  {
    return $this->getNearJieQi(true, LunarUtil::$QI);
  }

  /**
   * 获取上一气令（逆推的第一个气令）
   * @return JieQi|null 节气
   */
  public function getPrevQi()
  {
    return $this->getNearJieQi(false, LunarUtil::$QI);
  }

  /**
   * 获取下一节气（顺推的第一个节气）
   * @return JieQi|null 节气
   */
  public function getNextJieQi()
  {
    return $this->getNearJieQi(true, null);
  }

  /**
   * 获取上一节气（逆推的第一个节气）
   * @return JieQi|null 节气
   */
  public function getPrevJieQi()
  {
    return $this->getNearJieQi(false, null);
  }

  /**
   * 获取节气名称，如果无节气，返回空字符串
   * @return string 节气名称
   */
  public function getJieQi()
  {
    $name = '';
    foreach ($this->jieQi as $jq => $d) {
      if ($d->getYear() == $this->solar->getYear() && $d->getMonth() == $this->solar->getMonth() && $d->getDay() == $this->solar->getDay()) {
        $name = $jq;
        break;
      }
    }
    if (Lunar::$JIE_QI_APPEND == $name) {
      $name = Lunar::$JIE_QI_FIRST;
    } else if (Lunar::$JIE_QI_PREPEND == $name) {
      $name = Lunar::$JIE_QI_LAST;
    } else if (Lunar::$JIE_APPEND_SOLAR_FIRST == $name) {
      $name = Lunar::$JIE_SOLAR_FIRST;
    } else if (Lunar::$QI_APPEND_SOLAR_SECOND == $name) {
      $name = Lunar::$QI_SOLAR_SECOND;
    }
    return $name;
  }

  /**
   * 获取当天节气对象，如果无节气，返回null
   * @return JieQi|null 节气对象
   */
  public function getCurrentJieQi()
  {
    $name = $this->getJieQi();
    return strlen($name) > 0 ? new JieQi($name, $this->solar) : null;
  }

  /**
   * 获取当天节令对象，如果无节令，返回null
   * @return JieQi|null 节气对象
   */
  public function getCurrentJie()
  {
    $name = $this->getJie();
    return strlen($name) > 0 ? new JieQi($name, $this->solar) : null;
  }

  /**
   * 获取当天气令对象，如果无气令，返回null
   * @return JieQi|null 节气对象
   */
  public function getCurrentQi()
  {
    $name = $this->getQi();
    return strlen($name) > 0 ? new JieQi($name, $this->solar) : null;
  }

  public function getTimeGanIndex()
  {
    return $this->timeGanIndex;
  }

  public function getTimeZhiIndex()
  {
    return $this->timeZhiIndex;
  }

  public function getDayGanIndex()
  {
    return $this->dayGanIndex;
  }

  public function getDayZhiIndex()
  {
    return $this->dayZhiIndex;
  }

  public function getMonthGanIndex()
  {
    return $this->monthGanIndex;
  }

  public function getMonthZhiIndex()
  {
    return $this->monthZhiIndex;
  }

  public function getYearGanIndex()
  {
    return $this->yearGanIndex;
  }

  public function getYearZhiIndex()
  {
    return $this->yearZhiIndex;
  }

  public function getYearGanIndexByLiChun()
  {
    return $this->yearGanIndexByLiChun;
  }

  public function getYearZhiIndexByLiChun()
  {
    return $this->yearZhiIndexByLiChun;
  }

  public function getDayGanIndexExact()
  {
    return $this->dayGanIndexExact;
  }

  public function getDayGanIndexExact2()
  {
    return $this->dayGanIndexExact2;
  }

  public function getDayZhiIndexExact()
  {
    return $this->dayZhiIndexExact;
  }

  public function getDayZhiIndexExact2()
  {
    return $this->dayZhiIndexExact2;
  }

  public function getMonthGanIndexExact()
  {
    return $this->monthGanIndexExact;
  }

  public function getMonthZhiIndexExact()
  {
    return $this->monthZhiIndexExact;
  }

  public function getYearGanIndexExact()
  {
    return $this->yearGanIndexExact;
  }

  public function getYearZhiIndexExact()
  {
    return $this->yearZhiIndexExact;
  }

  public function getEightChar()
  {
    if (null == $this->eightChar) {
      $this->eightChar = EightChar::fromLunar($this);
    }
    return $this->eightChar;
  }

  /**
   * 获取往后推几天的农历日期，如果要往前推，则天数用负数
   * @param int days 天数
   * @return Lunar 农历日期
   */
  public function next($days)
  {
    $y = $this->year;
    $m = $this->month;
    $d = $this->day;
    if ($days > 0) {
      $daysInMonth = LunarUtil::getDaysOfMonth($y, $m);
      $rest = $this->day + $days;
      while ($daysInMonth < $rest) {
        if ($m > 0) {
          if (LunarUtil::getLeapMonth($y) != $m) {
            $m++;
          } else {
            $m = -$m;
          }
        } else {
          $m = 1 - $m;
        }
        if (13 == $m) {
          $y++;
          $m = 1;
        }
        $rest -= $daysInMonth;
        $daysInMonth = LunarUtil::getDaysOfMonth($y, $m);
      }
      $d = $rest;
    } else if ($days < 0) {
      $daysInMonth = $this->day;
      $rest = -$days;
      while ($daysInMonth <= $rest) {
        if ($m > 0) {
          $m--;
          if (0 == $m) {
            $y--;
            $m = LunarUtil::getLeapMonth($y) != 12 ? 12 : -12;
          }
        } else {
          $m = -$m;
        }
        $rest -= $daysInMonth;
        $daysInMonth = LunarUtil::getDaysOfMonth($y, $m);
      }
      $d = $daysInMonth - $rest;
    }
    return new Lunar($y, $m, $d, $this->hour, $this->minute, $this->second);
  }

  public function toFullString()
  {
    $s = '';
    $s .= $this;
    $s .= ' ';
    $s .= $this->getYearInGanZhi();
    $s .= '(';
    $s .= $this->getYearShengXiao();
    $s .= ')年 ';
    $s .= $this->getMonthInGanZhi();
    $s .= '(';
    $s .= $this->getMonthShengXiao();
    $s .= ')月 ';
    $s .= $this->getDayInGanZhi();
    $s .= '(';
    $s .= $this->getDayShengXiao();
    $s .= ')日 ';
    $s .= $this->getTimeZhi();
    $s .= '(';
    $s .= $this->getTimeShengXiao();
    $s .= ')时 纳音[';
    $s .= $this->getYearNaYin();
    $s .= ' ';
    $s .= $this->getMonthNaYin();
    $s .= ' ';
    $s .= $this->getDayNaYin();
    $s .= ' ';
    $s .= $this->getTimeNaYin();
    $s .= '] 星期';
    $s .= $this->getWeekInChinese();
    foreach ($this->getFestivals() as $f) {
      $s .= ' (' . $f . ')';
    }
    foreach ($this->getOtherFestivals() as $f) {
      $s .= ' (' . $f . ')';
    }
    $jq = $this->getJieQi();
    if (strlen($jq) > 0) {
      $s .= ' (' . $jq . ')';
    }
    $s .= ' ';
    $s .= $this->getGong();
    $s .= '方';
    $s .= $this->getShou();
    $s .= ' 星宿[';
    $s .= $this->getXiu();
    $s .= $this->getZheng();
    $s .= $this->getAnimal();
    $s .= '](';
    $s .= $this->getXiuLuck();
    $s .= ') 彭祖百忌[';
    $s .= $this->getPengZuGan();
    $s .= ' ';
    $s .= $this->getPengZuZhi();
    $s .= '] 喜神方位[';
    $s .= $this->getDayPositionXi();
    $s .= '](';
    $s .= $this->getDayPositionXiDesc();
    $s .= ') 阳贵神方位[';
    $s .= $this->getDayPositionYangGui();
    $s .= '](';
    $s .= $this->getDayPositionYangGuiDesc();
    $s .= ') 阴贵神方位[';
    $s .= $this->getDayPositionYinGui();
    $s .= '](';
    $s .= $this->getDayPositionYinGuiDesc();
    $s .= ') 福神方位[';
    $s .= $this->getDayPositionFu();
    $s .= '](';
    $s .= $this->getDayPositionFuDesc();
    $s .= ') 财神方位[';
    $s .= $this->getDayPositionCai();
    $s .= '](';
    $s .= $this->getDayPositionCaiDesc();
    $s .= ') 冲[';
    $s .= $this->getChongDesc();
    $s .= '] 煞[';
    $s .= $this->getSha();
    $s .= ']';
    return $s;
  }

  public function toString()
  {
    return $this->getYearInChinese() . '年' . $this->getMonthInChinese() . '月' . $this->getDayInChinese();
  }

  public function __toString()
  {
    return $this->toString();
  }

  /**
   * 获取年所在旬（以正月初一作为新年的开始）
   * @return string 旬
   */
  public function getYearXun()
  {
    return LunarUtil::getXun($this->getYearInGanZhi());
  }

  /**
   * 获取年所在旬（以立春当天作为新年的开始）
   * @return string 旬
   */
  public function getYearXunByLiChun()
  {
    return LunarUtil::getXun($this->getYearInGanZhiByLiChun());
  }

  /**
   * 获取年所在旬（以立春交接时刻作为新年的开始）
   * @return string 旬
   */
  public function getYearXunExact()
  {
    return LunarUtil::getXun($this->getYearInGanZhiExact());
  }

  /**
   * 获取值年空亡（以正月初一作为新年的开始）
   * @return string 空亡(旬空)
   */
  public function getYearXunKong()
  {
    return LunarUtil::getXunKong($this->getYearInGanZhi());
  }

  /**
   * 获取值年空亡（以立春当天作为新年的开始）
   * @return string 空亡(旬空)
   */
  public function getYearXunKongByLiChun()
  {
    return LunarUtil::getXunKong($this->getYearInGanZhiByLiChun());
  }

  /**
   * 获取值年空亡（以立春交接时刻作为新年的开始）
   * @return string 空亡(旬空)
   */
  public function getYearXunKongExact()
  {
    return LunarUtil::getXunKong($this->getYearInGanZhiExact());
  }

  /**
   * 获取月所在旬（以节交接当天起算）
   * @return string 旬
   */
  public function getMonthXun()
  {
    return LunarUtil::getXun($this->getMonthInGanZhi());
  }

  /**
   * 获取月所在旬（以节交接时刻起算）
   * @return string 旬
   */
  public function getMonthXunExact()
  {
    return LunarUtil::getXun($this->getMonthInGanZhiExact());
  }

  /**
   * 获取值月空亡（以节交接当天起算）
   * @return string 空亡(旬空)
   */
  public function getMonthXunKong()
  {
    return LunarUtil::getXunKong($this->getMonthInGanZhi());
  }

  /**
   * 获取值月空亡（以节交接时刻起算）
   * @return string 空亡(旬空)
   */
  public function getMonthXunKongExact()
  {
    return LunarUtil::getXunKong($this->getMonthInGanZhiExact());
  }

  /**
   * 获取日所在旬（以节交接当天起算）
   * @return string 旬
   */
  public function getDayXun()
  {
    return LunarUtil::getXun($this->getDayInGanZhi());
  }

  /**
   * 获取日所在旬（八字流派1，晚子时日柱算明天）
   * @return string 旬
   */
  public function getDayXunExact()
  {
    return LunarUtil::getXun($this->getDayInGanZhiExact());
  }

  /**
   * 获取日所在旬（八字流派2，晚子时日柱算当天）
   * @return string 旬
   */
  public function getDayXunExact2()
  {
    return LunarUtil::getXun($this->getDayInGanZhiExact2());
  }

  /**
   * 获取值日空亡
   * @return string 空亡(旬空)
   */
  public function getDayXunKong()
  {
    return LunarUtil::getXunKong($this->getDayInGanZhi());
  }

  /**
   * 获取值日空亡（八字流派1，晚子时日柱算明天）
   * @return string 空亡(旬空)
   */
  public function getDayXunKongExact()
  {
    return LunarUtil::getXunKong($this->getDayInGanZhiExact());
  }

  /**
   * 获取值日空亡（八字流派2，晚子时日柱算当天）
   * @return string 空亡(旬空)
   */
  public function getDayXunKongExact2()
  {
    return LunarUtil::getXunKong($this->getDayInGanZhiExact2());
  }

  /**
   * 获取时辰所在旬
   * @return string 旬
   */
  public function getTimeXun()
  {
    return LunarUtil::getXun($this->getTimeInGanZhi());
  }

  /**
   * 获取值时空亡
   * @return string 空亡(旬空)
   */
  public function getTimeXunKong()
  {
    return LunarUtil::getXunKong($this->getTimeInGanZhi());
  }

  public function getShuJiu()
  {
    try {
      $currentCalendar = new DateTime($this->solar->getYear() . '-' . $this->solar->getMonth() . '-' . $this->solar->getDay() . ' 0:0:0');
    } catch (Exception $e) {
      return null;
    }
    $start = $this->jieQi[Lunar::$JIE_QI_APPEND];
    try {
      $startCalendar = new DateTime($start->getYear() . '-' . $start->getMonth() . '-' . $start->getDay() . ' 0:0:0');
    } catch (Exception $e) {
      return null;
    }
    if ($currentCalendar < $startCalendar) {
      $start = $this->jieQi[Lunar::$JIE_QI_FIRST];
      try {
        $startCalendar = new DateTime($start->getYear() . '-' . $start->getMonth() . '-' . $start->getDay() . ' 0:0:0');
      } catch (Exception $e) {
        return null;
      }
    }
    try {
      $endCalendar = new DateTime($start->getYear() . '-' . $start->getMonth() . '-' . $start->getDay() . ' 0:0:0');
    } catch (Exception $e) {
      return null;
    }
    $endCalendar->modify('+81 day');
    if ($currentCalendar < $startCalendar || $currentCalendar >= $endCalendar) {
      return null;
    }
    $days = intval(floor(($currentCalendar->getTimestamp() - $startCalendar->getTimestamp()) / 86400));
    return new ShuJiu(LunarUtil::$NUMBER[$days / 9 + 1] . '九', $days % 9 + 1);
  }

  public function getFu()
  {
    try {
      $currentCalendar = new DateTime($this->solar->getYear() . '-' . $this->solar->getMonth() . '-' . $this->solar->getDay() . ' 0:0:0');
    } catch (Exception $e) {
      return null;
    }
    $xiaZhi = $this->jieQi['夏至'];
    $liQiu = $this->jieQi['立秋'];
    try {
      $startCalendar = new DateTime($xiaZhi->getYear() . '-' . $xiaZhi->getMonth() . '-' . $xiaZhi->getDay() . ' 0:0:0');
    } catch (Exception $e) {
      return null;
    }
    $add = 6 - $xiaZhi->getLunar()->getDayGanIndex();
    if ($add < 0) {
      $add += 10;
    }
    $add += 20;
    $startCalendar->modify('+' . $add . ' day');
    if ($currentCalendar < $startCalendar) {
      return null;
    }
    $seconds = 86400;
    $days = intval(floor(($currentCalendar->getTimestamp() - $startCalendar->getTimestamp()) / $seconds));
    if ($days < 10) {
      return new Fu('初伏', $days + 1);
    }
    $startCalendar->modify('+10 day');
    $days = intval(floor(($currentCalendar->getTimestamp() - $startCalendar->getTimestamp()) / $seconds));
    if ($days < 10) {
      return new Fu('中伏', $days + 1);
    }
    $startCalendar->modify('+10 day');
    $days = intval(floor(($currentCalendar->getTimestamp() - $startCalendar->getTimestamp()) / $seconds));
    try {
      $liQiuCalendar = new DateTime($liQiu->getYear() . '-' . $liQiu->getMonth() . '-' . $liQiu->getDay() . ' 0:0:0');
    } catch (Exception $e) {
      return null;
    }
    if ($liQiuCalendar <= $startCalendar) {
      if ($days < 10) {
        return new Fu('末伏', $days + 1);
      }
    } else {
      if ($days < 10) {
        return new Fu('中伏', $days + 11);
      }
      $startCalendar->modify('+10 day');
      $days = intval(floor(($currentCalendar->getTimestamp() - $startCalendar->getTimestamp()) / $seconds));
      if ($days < 10) {
        return new Fu('末伏', $days + 1);
      }
    }
    return null;
  }

  /**
   * 获取六曜
   * @return string 六曜
   */
  public function getLiuYao()
  {
    return LunarUtil::$LIU_YAO[(abs($this->month) + $this->day - 2) % 6];
  }

  /**
   * 获取物候
   * @return string 物候
   */
  public function getWuHou()
  {
    $jieQi = $this->getPrevJieQi();
    $name = $jieQi->getName();
    $offset = 0;
    for ($i = 0, $j = count(Lunar::$JIE_QI); $i < $j; $i++) {
      if (strcmp($name, Lunar::$JIE_QI[$i]) === 0) {
        $offset = $i;
        break;
      }
    }
    try {
      $currentCalendar = new DateTime($this->solar->getYear() . '-' . $this->solar->getMonth() . '-' . $this->solar->getDay() . ' 0:0:0');
    } catch (Exception $e) {
      return '';
    }
    $startSolar = $jieQi->getSolar();
    try {
      $startCalendar = new DateTime($startSolar->getYear() . '-' . $startSolar->getMonth() . '-' . $startSolar->getDay() . ' 0:0:0');
    } catch (Exception $e) {
      return '';
    }
    $days = intval(floor(($currentCalendar->getTimestamp() - $startCalendar->getTimestamp()) / 86400));
    return LunarUtil::$WU_HOU[$offset * 3 + floor($days / 5)];
  }

}
